omnimancer-cli 0.1.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.
- omnimancer/__init__.py +42 -0
- omnimancer/__main__.py +9 -0
- omnimancer/cli/__init__.py +8 -0
- omnimancer/cli/agent_manager.py +826 -0
- omnimancer/cli/agent_wizard.py +944 -0
- omnimancer/cli/approval_formatter.py +734 -0
- omnimancer/cli/approval_integration.py +734 -0
- omnimancer/cli/approval_prompt.py +1286 -0
- omnimancer/cli/batch_approval_display.py +617 -0
- omnimancer/cli/batch_approval_filters.py +729 -0
- omnimancer/cli/batch_operation_monitor.py +775 -0
- omnimancer/cli/commands/performance_cmd.py +624 -0
- omnimancer/cli/commands.py +757 -0
- omnimancer/cli/completion_handler.py +281 -0
- omnimancer/cli/config_setup_wizard.py +783 -0
- omnimancer/cli/dynamic_commands.py +371 -0
- omnimancer/cli/handlers/__init__.py +18 -0
- omnimancer/cli/handlers/agent_handler.py +865 -0
- omnimancer/cli/handlers/agent_persona_handler.py +1048 -0
- omnimancer/cli/handlers/custom_agent_handler.py +352 -0
- omnimancer/cli/handlers/permissions_handler.py +1609 -0
- omnimancer/cli/interface.py +6695 -0
- omnimancer/cli/performance_dashboard.py +612 -0
- omnimancer/core/__init__.py +34 -0
- omnimancer/core/agent/__init__.py +256 -0
- omnimancer/core/agent/agent_config.py +715 -0
- omnimancer/core/agent/agent_switcher.py +668 -0
- omnimancer/core/agent/approval_context.py +460 -0
- omnimancer/core/agent/approval_dialog.py +902 -0
- omnimancer/core/agent/approval_interface.py +628 -0
- omnimancer/core/agent/approval_manager.py +760 -0
- omnimancer/core/agent/cli_integration.py +470 -0
- omnimancer/core/agent/config.py +845 -0
- omnimancer/core/agent/custom_agent_integration.py +654 -0
- omnimancer/core/agent/diff_renderer.py +706 -0
- omnimancer/core/agent/file_content_display.py +503 -0
- omnimancer/core/agent/file_modification_workflow.py +658 -0
- omnimancer/core/agent/file_system_manager.py +1790 -0
- omnimancer/core/agent/input_handler.py +614 -0
- omnimancer/core/agent/metrics_collector.py +771 -0
- omnimancer/core/agent/optimization_engine.py +729 -0
- omnimancer/core/agent/performance_monitor.py +717 -0
- omnimancer/core/agent/persona.py +870 -0
- omnimancer/core/agent/persona_validator.py +672 -0
- omnimancer/core/agent/program_executor.py +748 -0
- omnimancer/core/agent/proposed_changes_integration.py +663 -0
- omnimancer/core/agent/read_before_write_errors.py +492 -0
- omnimancer/core/agent/read_before_write_ui.py +647 -0
- omnimancer/core/agent/rich_renderer.py +763 -0
- omnimancer/core/agent/status_config.py +238 -0
- omnimancer/core/agent/status_core.py +446 -0
- omnimancer/core/agent/status_integrated_engine.py +540 -0
- omnimancer/core/agent/status_manager.py +878 -0
- omnimancer/core/agent/status_ui_components.py +535 -0
- omnimancer/core/agent/template_applicator.py +548 -0
- omnimancer/core/agent/terminal_status_listener.py +394 -0
- omnimancer/core/agent/token_tracker.py +679 -0
- omnimancer/core/agent/types.py +60 -0
- omnimancer/core/agent/web_client.py +745 -0
- omnimancer/core/agent/workflow_orchestrator.py +826 -0
- omnimancer/core/agent_engine.py +1625 -0
- omnimancer/core/agent_mode_manager.py +706 -0
- omnimancer/core/agent_progress_ui.py +545 -0
- omnimancer/core/chat_manager.py +141 -0
- omnimancer/core/config_manager.py +2199 -0
- omnimancer/core/config_migration.py +772 -0
- omnimancer/core/config_provider.py +1974 -0
- omnimancer/core/config_security_validator.py +393 -0
- omnimancer/core/config_validator.py +768 -0
- omnimancer/core/conversation_manager.py +352 -0
- omnimancer/core/engine.py +787 -0
- omnimancer/core/enhanced_input.py +523 -0
- omnimancer/core/env_loader.py +83 -0
- omnimancer/core/fallback_manager.py +568 -0
- omnimancer/core/health_monitor.py +462 -0
- omnimancer/core/history_manager.py +462 -0
- omnimancer/core/mcp_integration_layer.py +878 -0
- omnimancer/core/models.py +1889 -0
- omnimancer/core/provider_capabilities.py +403 -0
- omnimancer/core/provider_initializer.py +450 -0
- omnimancer/core/provider_registry.py +432 -0
- omnimancer/core/security/__init__.py +16 -0
- omnimancer/core/security/approval_workflow.py +406 -0
- omnimancer/core/security/audit_logger.py +511 -0
- omnimancer/core/security/permission_controller.py +511 -0
- omnimancer/core/security/sandbox_manager.py +379 -0
- omnimancer/core/security/security_manager.py +530 -0
- omnimancer/core/setup_wizard.py +345 -0
- omnimancer/core/setup_wizard_core.py +449 -0
- omnimancer/core/setup_wizard_guide_generator.py +376 -0
- omnimancer/core/setup_wizard_provider_setup.py +454 -0
- omnimancer/core/setup_wizard_ui.py +317 -0
- omnimancer/core/setup_wizard_validation.py +371 -0
- omnimancer/core/signal_handler.py +174 -0
- omnimancer/mcp/__init__.py +11 -0
- omnimancer/mcp/client.py +725 -0
- omnimancer/mcp/manager.py +649 -0
- omnimancer/providers/__init__.py +24 -0
- omnimancer/providers/azure.py +608 -0
- omnimancer/providers/base.py +262 -0
- omnimancer/providers/bedrock.py +711 -0
- omnimancer/providers/claude.py +426 -0
- omnimancer/providers/claude_code.py +406 -0
- omnimancer/providers/cohere.py +412 -0
- omnimancer/providers/factory.py +988 -0
- omnimancer/providers/gemini.py +708 -0
- omnimancer/providers/mistral.py +554 -0
- omnimancer/providers/ollama.py +510 -0
- omnimancer/providers/openai.py +362 -0
- omnimancer/providers/openrouter.py +709 -0
- omnimancer/providers/perplexity.py +476 -0
- omnimancer/providers/vertex.py +617 -0
- omnimancer/providers/xai.py +484 -0
- omnimancer/ui/__init__.py +6 -0
- omnimancer/ui/cancellation_handler.py +235 -0
- omnimancer/ui/progress_indicator.py +318 -0
- omnimancer/utils/__init__.py +22 -0
- omnimancer/utils/error_handler.py +589 -0
- omnimancer/utils/errors.py +667 -0
- omnimancer/utils/retry.py +238 -0
- omnimancer_cli-0.1.0.dist-info/METADATA +413 -0
- omnimancer_cli-0.1.0.dist-info/RECORD +126 -0
- omnimancer_cli-0.1.0.dist-info/WHEEL +5 -0
- omnimancer_cli-0.1.0.dist-info/entry_points.txt +4 -0
- omnimancer_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- omnimancer_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom Agent Integration with Omnimancer Security and Approval Systems.
|
|
3
|
+
|
|
4
|
+
This module provides the integration layer that allows custom agents to work
|
|
5
|
+
seamlessly with the existing security framework, approval workflows, and
|
|
6
|
+
permission systems.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from typing import Any, Dict, List, Optional
|
|
11
|
+
|
|
12
|
+
from omnimancer.core.models import ConfigTemplateManager
|
|
13
|
+
|
|
14
|
+
from ..security.audit_logger import AuditEventType, AuditLevel, AuditLogger
|
|
15
|
+
from ..security.permission_controller import PermissionController
|
|
16
|
+
from .agent_config import (
|
|
17
|
+
AgentRepository,
|
|
18
|
+
AgentTool,
|
|
19
|
+
CustomAgentConfig,
|
|
20
|
+
)
|
|
21
|
+
from .approval_manager import EnhancedApprovalManager
|
|
22
|
+
from .config import (
|
|
23
|
+
AgentConfig,
|
|
24
|
+
AgentSettings,
|
|
25
|
+
FileSystemSettings,
|
|
26
|
+
ProviderConfig,
|
|
27
|
+
SecuritySettings,
|
|
28
|
+
WebClientSettings,
|
|
29
|
+
)
|
|
30
|
+
from .persona import PersonaCapability
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class CustomAgentIntegration:
|
|
36
|
+
"""Integration layer for custom agents with Omnimancer systems."""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
repository: Optional[AgentRepository] = None,
|
|
41
|
+
template_manager: Optional[ConfigTemplateManager] = None,
|
|
42
|
+
permission_controller: Optional[PermissionController] = None,
|
|
43
|
+
audit_logger: Optional[AuditLogger] = None,
|
|
44
|
+
):
|
|
45
|
+
"""
|
|
46
|
+
Initialize the integration layer.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
repository: Agent repository for storage
|
|
50
|
+
template_manager: Configuration template manager
|
|
51
|
+
permission_controller: Permission controller
|
|
52
|
+
audit_logger: Audit logger for security events
|
|
53
|
+
"""
|
|
54
|
+
self.repository = repository or AgentRepository()
|
|
55
|
+
self.template_manager = template_manager or ConfigTemplateManager()
|
|
56
|
+
self.permission_controller = permission_controller or PermissionController()
|
|
57
|
+
self.audit_logger = audit_logger or AuditLogger()
|
|
58
|
+
|
|
59
|
+
# Cache for converted configurations
|
|
60
|
+
self._config_cache: Dict[str, AgentConfig] = {}
|
|
61
|
+
|
|
62
|
+
# Track active custom agent
|
|
63
|
+
self._active_custom_agent: Optional[CustomAgentConfig] = None
|
|
64
|
+
|
|
65
|
+
def convert_custom_to_standard_config(
|
|
66
|
+
self, custom_config: CustomAgentConfig
|
|
67
|
+
) -> AgentConfig:
|
|
68
|
+
"""
|
|
69
|
+
Convert custom agent configuration to standard AgentConfig.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
custom_config: Custom agent configuration
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Standard AgentConfig compatible with existing systems
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
# Check cache first
|
|
79
|
+
if custom_config.id in self._config_cache:
|
|
80
|
+
cached_config = self._config_cache[custom_config.id]
|
|
81
|
+
# Verify cache is still valid (check timestamps)
|
|
82
|
+
if cached_config.updated_at >= custom_config.updated_at:
|
|
83
|
+
return cached_config
|
|
84
|
+
|
|
85
|
+
# Create base AgentConfig
|
|
86
|
+
agent_config = AgentConfig(auto_save=False)
|
|
87
|
+
|
|
88
|
+
# Apply security settings with overrides
|
|
89
|
+
security_settings = self._build_security_settings(custom_config)
|
|
90
|
+
agent_config.security = security_settings
|
|
91
|
+
|
|
92
|
+
# Apply agent settings with overrides
|
|
93
|
+
agent_settings = self._build_agent_settings(custom_config)
|
|
94
|
+
agent_config.agent = agent_settings
|
|
95
|
+
|
|
96
|
+
# Build provider configuration from model settings
|
|
97
|
+
provider_config = self._build_provider_config(custom_config)
|
|
98
|
+
provider_id = f"custom_{custom_config.id[:8]}"
|
|
99
|
+
agent_config.add_provider_config(provider_id, provider_config)
|
|
100
|
+
|
|
101
|
+
# Apply tool-specific settings
|
|
102
|
+
file_system_settings = self._build_filesystem_settings(custom_config)
|
|
103
|
+
agent_config.filesystem = file_system_settings
|
|
104
|
+
|
|
105
|
+
web_client_settings = self._build_webclient_settings(custom_config)
|
|
106
|
+
agent_config.web_client = web_client_settings
|
|
107
|
+
|
|
108
|
+
# Cache the converted configuration
|
|
109
|
+
self._config_cache[custom_config.id] = agent_config
|
|
110
|
+
|
|
111
|
+
# Log the conversion
|
|
112
|
+
self.audit_logger.log_event(
|
|
113
|
+
AuditEventType.SYSTEM_EVENT,
|
|
114
|
+
AuditLevel.INFO,
|
|
115
|
+
f"Converted custom agent '{custom_config.name}' to standard config",
|
|
116
|
+
metadata={
|
|
117
|
+
"agent_id": custom_config.id,
|
|
118
|
+
"agent_name": custom_config.name,
|
|
119
|
+
"provider": custom_config.model_settings.provider_type.value,
|
|
120
|
+
"tools_count": len(custom_config.enabled_tools),
|
|
121
|
+
"capabilities_count": len(custom_config.capabilities),
|
|
122
|
+
},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return agent_config
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.error(f"Failed to convert custom agent config: {e}", exc_info=True)
|
|
129
|
+
self.audit_logger.log_event(
|
|
130
|
+
AuditEventType.SYSTEM_EVENT,
|
|
131
|
+
AuditLevel.ERROR,
|
|
132
|
+
f"Failed to convert custom agent '{custom_config.name}': {e}",
|
|
133
|
+
metadata={"agent_id": custom_config.id, "error": str(e)},
|
|
134
|
+
)
|
|
135
|
+
raise
|
|
136
|
+
|
|
137
|
+
def _build_security_settings(
|
|
138
|
+
self, custom_config: CustomAgentConfig
|
|
139
|
+
) -> SecuritySettings:
|
|
140
|
+
"""Build security settings from custom agent configuration."""
|
|
141
|
+
# Start with default security settings
|
|
142
|
+
security = SecuritySettings()
|
|
143
|
+
|
|
144
|
+
# Apply security level-based defaults
|
|
145
|
+
safety_level = custom_config.behavior_rules.safety_level
|
|
146
|
+
|
|
147
|
+
if safety_level == "strict":
|
|
148
|
+
security.auto_approve_safe_operations = False
|
|
149
|
+
security.backup_before_changes = True
|
|
150
|
+
security.enable_sandboxing = True
|
|
151
|
+
security.enable_audit_logging = True
|
|
152
|
+
security.audit_log_level = "INFO"
|
|
153
|
+
elif safety_level == "standard":
|
|
154
|
+
security.auto_approve_safe_operations = False
|
|
155
|
+
security.backup_before_changes = True
|
|
156
|
+
security.enable_sandboxing = True
|
|
157
|
+
security.enable_audit_logging = True
|
|
158
|
+
security.audit_log_level = "INFO"
|
|
159
|
+
elif safety_level == "permissive":
|
|
160
|
+
security.auto_approve_safe_operations = True
|
|
161
|
+
security.backup_before_changes = True
|
|
162
|
+
security.enable_sandboxing = False
|
|
163
|
+
security.enable_audit_logging = True
|
|
164
|
+
security.audit_log_level = "WARNING"
|
|
165
|
+
|
|
166
|
+
# Apply any security overrides from custom config
|
|
167
|
+
if custom_config.security_overrides:
|
|
168
|
+
for key, value in custom_config.security_overrides.items():
|
|
169
|
+
if hasattr(security, key):
|
|
170
|
+
setattr(security, key, value)
|
|
171
|
+
|
|
172
|
+
# Adjust based on enabled tools
|
|
173
|
+
if AgentTool.PROGRAM_EXECUTOR not in custom_config.enabled_tools:
|
|
174
|
+
# Remove commands from allowed list if tool is disabled
|
|
175
|
+
security.allowed_commands = []
|
|
176
|
+
|
|
177
|
+
# Apply confirmation requirements
|
|
178
|
+
confirmation_patterns = custom_config.behavior_rules.require_confirmation_for
|
|
179
|
+
if "file_delete" in confirmation_patterns:
|
|
180
|
+
# This would be handled by approval workflow
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
return security
|
|
184
|
+
|
|
185
|
+
def _build_agent_settings(self, custom_config: CustomAgentConfig) -> AgentSettings:
|
|
186
|
+
"""Build agent settings from custom agent configuration."""
|
|
187
|
+
agent_settings = AgentSettings()
|
|
188
|
+
|
|
189
|
+
# Configure based on context parameters
|
|
190
|
+
context = custom_config.context_parameters
|
|
191
|
+
|
|
192
|
+
agent_settings.enable_learning = context.conversation_memory
|
|
193
|
+
agent_settings.remember_user_preferences = context.conversation_memory
|
|
194
|
+
agent_settings.verbose_logging = False # Default to quiet
|
|
195
|
+
agent_settings.enable_progress_reporting = True
|
|
196
|
+
|
|
197
|
+
# Apply reasoning style settings
|
|
198
|
+
reasoning = custom_config.behavior_rules.reasoning_style
|
|
199
|
+
if reasoning == "verbose":
|
|
200
|
+
agent_settings.verbose_logging = True
|
|
201
|
+
elif reasoning == "concise":
|
|
202
|
+
agent_settings.verbose_logging = False
|
|
203
|
+
|
|
204
|
+
# Apply any agent overrides
|
|
205
|
+
if custom_config.agent_overrides:
|
|
206
|
+
for key, value in custom_config.agent_overrides.items():
|
|
207
|
+
if hasattr(agent_settings, key):
|
|
208
|
+
setattr(agent_settings, key, value)
|
|
209
|
+
|
|
210
|
+
return agent_settings
|
|
211
|
+
|
|
212
|
+
def _build_provider_config(
|
|
213
|
+
self, custom_config: CustomAgentConfig
|
|
214
|
+
) -> ProviderConfig:
|
|
215
|
+
"""Build provider configuration from model settings."""
|
|
216
|
+
model_settings = custom_config.model_settings
|
|
217
|
+
|
|
218
|
+
return ProviderConfig(
|
|
219
|
+
provider_type=model_settings.provider_type,
|
|
220
|
+
enabled=True,
|
|
221
|
+
model=model_settings.model_name,
|
|
222
|
+
temperature=model_settings.temperature,
|
|
223
|
+
max_tokens=model_settings.max_tokens,
|
|
224
|
+
timeout_seconds=30, # Default timeout
|
|
225
|
+
retry_attempts=3,
|
|
226
|
+
provider_specific={
|
|
227
|
+
"custom_agent_id": custom_config.id,
|
|
228
|
+
"custom_agent_name": custom_config.name,
|
|
229
|
+
"context_window": custom_config.context_parameters.context_window_size,
|
|
230
|
+
"system_prompt": custom_config.context_parameters.system_prompt,
|
|
231
|
+
"response_format": custom_config.context_parameters.response_format,
|
|
232
|
+
},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def _build_filesystem_settings(
|
|
236
|
+
self, custom_config: CustomAgentConfig
|
|
237
|
+
) -> FileSystemSettings:
|
|
238
|
+
"""Build filesystem settings based on enabled tools."""
|
|
239
|
+
fs_settings = FileSystemSettings()
|
|
240
|
+
|
|
241
|
+
if AgentTool.FILE_OPERATIONS not in custom_config.enabled_tools:
|
|
242
|
+
# Disable file operations
|
|
243
|
+
fs_settings.enable_atomic_operations = False
|
|
244
|
+
fs_settings.enable_version_control = False
|
|
245
|
+
else:
|
|
246
|
+
# Enhanced settings for file operations
|
|
247
|
+
safety_level = custom_config.behavior_rules.safety_level
|
|
248
|
+
|
|
249
|
+
if safety_level == "strict":
|
|
250
|
+
fs_settings.enable_atomic_operations = True
|
|
251
|
+
fs_settings.backup_directory = (
|
|
252
|
+
f"/tmp/omnimancer_backups_{custom_config.id[:8]}"
|
|
253
|
+
)
|
|
254
|
+
fs_settings.enable_version_control = True
|
|
255
|
+
fs_settings.git_auto_add = False
|
|
256
|
+
elif safety_level == "permissive":
|
|
257
|
+
fs_settings.enable_atomic_operations = True
|
|
258
|
+
fs_settings.enable_version_control = False
|
|
259
|
+
fs_settings.git_auto_add = False
|
|
260
|
+
|
|
261
|
+
return fs_settings
|
|
262
|
+
|
|
263
|
+
def _build_webclient_settings(
|
|
264
|
+
self, custom_config: CustomAgentConfig
|
|
265
|
+
) -> WebClientSettings:
|
|
266
|
+
"""Build web client settings based on enabled tools."""
|
|
267
|
+
web_settings = WebClientSettings()
|
|
268
|
+
|
|
269
|
+
if AgentTool.WEB_CLIENT not in custom_config.enabled_tools:
|
|
270
|
+
# Disable web client
|
|
271
|
+
web_settings.enabled = False
|
|
272
|
+
else:
|
|
273
|
+
web_settings.enabled = True
|
|
274
|
+
|
|
275
|
+
# Configure based on capabilities
|
|
276
|
+
if PersonaCapability.WEB_SEARCH in custom_config.capabilities:
|
|
277
|
+
web_settings.enable_caching = True
|
|
278
|
+
web_settings.cache_ttl_seconds = 3600
|
|
279
|
+
|
|
280
|
+
# Safety-based rate limiting
|
|
281
|
+
safety_level = custom_config.behavior_rules.safety_level
|
|
282
|
+
if safety_level == "strict":
|
|
283
|
+
web_settings.requests_per_second = 2.0
|
|
284
|
+
web_settings.requests_per_minute = 30.0
|
|
285
|
+
web_settings.requests_per_hour = 100.0
|
|
286
|
+
elif safety_level == "permissive":
|
|
287
|
+
web_settings.requests_per_second = 10.0
|
|
288
|
+
web_settings.requests_per_minute = 200.0
|
|
289
|
+
web_settings.requests_per_hour = 2000.0
|
|
290
|
+
|
|
291
|
+
return web_settings
|
|
292
|
+
|
|
293
|
+
def apply_permission_overrides(self, custom_config: CustomAgentConfig) -> None:
|
|
294
|
+
"""
|
|
295
|
+
Apply custom agent permission rules to the permission controller.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
custom_config: Custom agent configuration
|
|
299
|
+
"""
|
|
300
|
+
try:
|
|
301
|
+
# Apply tool-based restrictions
|
|
302
|
+
if AgentTool.FILE_OPERATIONS not in custom_config.enabled_tools:
|
|
303
|
+
# Remove file operation permissions
|
|
304
|
+
restricted_patterns = [
|
|
305
|
+
"file_read",
|
|
306
|
+
"file_write",
|
|
307
|
+
"file_delete",
|
|
308
|
+
"directory_create",
|
|
309
|
+
"directory_delete",
|
|
310
|
+
]
|
|
311
|
+
for pattern in restricted_patterns:
|
|
312
|
+
# This would be implemented based on PermissionController API
|
|
313
|
+
pass
|
|
314
|
+
|
|
315
|
+
if AgentTool.PROGRAM_EXECUTOR not in custom_config.enabled_tools:
|
|
316
|
+
# Clear allowed commands
|
|
317
|
+
self.permission_controller.allowed_commands.clear()
|
|
318
|
+
|
|
319
|
+
# Apply custom restrictions
|
|
320
|
+
for restriction in custom_config.behavior_rules.custom_restrictions:
|
|
321
|
+
# Parse and apply restriction
|
|
322
|
+
self._apply_custom_restriction(restriction)
|
|
323
|
+
|
|
324
|
+
# Apply auto-approval patterns
|
|
325
|
+
for pattern in custom_config.behavior_rules.auto_approve_patterns:
|
|
326
|
+
# This would store approval patterns
|
|
327
|
+
self._apply_auto_approval_pattern(pattern, custom_config)
|
|
328
|
+
|
|
329
|
+
self.audit_logger.log_event(
|
|
330
|
+
AuditEventType.PERMISSION_CHECK,
|
|
331
|
+
AuditLevel.INFO,
|
|
332
|
+
f"Applied permission overrides for custom agent '{custom_config.name}'",
|
|
333
|
+
metadata={
|
|
334
|
+
"agent_id": custom_config.id,
|
|
335
|
+
"enabled_tools": [
|
|
336
|
+
tool.value for tool in custom_config.enabled_tools
|
|
337
|
+
],
|
|
338
|
+
"restrictions_count": len(
|
|
339
|
+
custom_config.behavior_rules.custom_restrictions
|
|
340
|
+
),
|
|
341
|
+
"auto_approve_count": len(
|
|
342
|
+
custom_config.behavior_rules.auto_approve_patterns
|
|
343
|
+
),
|
|
344
|
+
},
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
except Exception as e:
|
|
348
|
+
logger.error(f"Failed to apply permission overrides: {e}", exc_info=True)
|
|
349
|
+
self.audit_logger.log_event(
|
|
350
|
+
AuditEventType.SECURITY_ALERT,
|
|
351
|
+
AuditLevel.ERROR,
|
|
352
|
+
f"Failed to apply permissions for custom agent: {e}",
|
|
353
|
+
metadata={"agent_id": custom_config.id, "error": str(e)},
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
def _apply_custom_restriction(self, restriction: str) -> None:
|
|
357
|
+
"""Apply a custom restriction rule."""
|
|
358
|
+
# Parse restriction format (e.g., "block:*.env", "require_approval:system_commands")
|
|
359
|
+
if ":" in restriction:
|
|
360
|
+
action, target = restriction.split(":", 1)
|
|
361
|
+
|
|
362
|
+
if action == "block":
|
|
363
|
+
self.permission_controller.add_restricted_path(target)
|
|
364
|
+
elif action == "require_approval":
|
|
365
|
+
# This would be handled by the approval system
|
|
366
|
+
pass
|
|
367
|
+
elif action == "deny_command":
|
|
368
|
+
self.permission_controller.remove_allowed_command(target)
|
|
369
|
+
|
|
370
|
+
def _apply_auto_approval_pattern(
|
|
371
|
+
self, pattern: str, custom_config: CustomAgentConfig
|
|
372
|
+
) -> None:
|
|
373
|
+
"""Apply an auto-approval pattern."""
|
|
374
|
+
# Store pattern for future automatic approval
|
|
375
|
+
# This would integrate with the permission controller's approval memory
|
|
376
|
+
pass
|
|
377
|
+
|
|
378
|
+
def setup_approval_integration(
|
|
379
|
+
self,
|
|
380
|
+
custom_config: CustomAgentConfig,
|
|
381
|
+
approval_manager: EnhancedApprovalManager,
|
|
382
|
+
) -> None:
|
|
383
|
+
"""
|
|
384
|
+
Set up approval workflow integration for custom agent.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
custom_config: Custom agent configuration
|
|
388
|
+
approval_manager: Enhanced approval manager
|
|
389
|
+
"""
|
|
390
|
+
try:
|
|
391
|
+
# Configure approval requirements based on behavior rules
|
|
392
|
+
confirmation_requirements = (
|
|
393
|
+
custom_config.behavior_rules.require_confirmation_for
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
# Set up approval callbacks with custom logic
|
|
397
|
+
def custom_approval_filter(
|
|
398
|
+
operation_type: str, operation_data: Dict[str, Any]
|
|
399
|
+
) -> bool:
|
|
400
|
+
"""Filter function for determining if approval is needed."""
|
|
401
|
+
|
|
402
|
+
# Check if operation type requires confirmation
|
|
403
|
+
if operation_type in confirmation_requirements:
|
|
404
|
+
return True
|
|
405
|
+
|
|
406
|
+
# Check safety level
|
|
407
|
+
safety_level = custom_config.behavior_rules.safety_level
|
|
408
|
+
|
|
409
|
+
if safety_level == "strict":
|
|
410
|
+
# Require approval for most operations
|
|
411
|
+
risky_operations = [
|
|
412
|
+
"file_write",
|
|
413
|
+
"file_delete",
|
|
414
|
+
"command_execute",
|
|
415
|
+
"web_request",
|
|
416
|
+
"system_command",
|
|
417
|
+
]
|
|
418
|
+
return operation_type in risky_operations
|
|
419
|
+
|
|
420
|
+
elif safety_level == "permissive":
|
|
421
|
+
# Only require approval for very dangerous operations
|
|
422
|
+
dangerous_operations = ["file_delete", "system_command"]
|
|
423
|
+
return operation_type in dangerous_operations
|
|
424
|
+
|
|
425
|
+
else: # standard
|
|
426
|
+
# Default approval requirements
|
|
427
|
+
moderate_operations = [
|
|
428
|
+
"file_delete",
|
|
429
|
+
"command_execute",
|
|
430
|
+
"system_command",
|
|
431
|
+
]
|
|
432
|
+
return operation_type in moderate_operations
|
|
433
|
+
|
|
434
|
+
# Apply the filter to the approval manager
|
|
435
|
+
# This would be implemented based on the approval manager's API
|
|
436
|
+
|
|
437
|
+
self.audit_logger.log_event(
|
|
438
|
+
AuditEventType.SYSTEM_EVENT,
|
|
439
|
+
AuditLevel.INFO,
|
|
440
|
+
f"Configured approval integration for custom agent '{custom_config.name}'",
|
|
441
|
+
metadata={
|
|
442
|
+
"agent_id": custom_config.id,
|
|
443
|
+
"safety_level": custom_config.behavior_rules.safety_level,
|
|
444
|
+
"confirmation_types": confirmation_requirements,
|
|
445
|
+
},
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
except Exception as e:
|
|
449
|
+
logger.error(f"Failed to setup approval integration: {e}", exc_info=True)
|
|
450
|
+
self.audit_logger.log_event(
|
|
451
|
+
AuditEventType.SECURITY_ALERT,
|
|
452
|
+
AuditLevel.ERROR,
|
|
453
|
+
f"Failed to setup approval integration: {e}",
|
|
454
|
+
metadata={"agent_id": custom_config.id, "error": str(e)},
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
def activate_custom_agent(self, custom_config: CustomAgentConfig) -> AgentConfig:
|
|
458
|
+
"""
|
|
459
|
+
Activate a custom agent by converting and applying its configuration.
|
|
460
|
+
|
|
461
|
+
Args:
|
|
462
|
+
custom_config: Custom agent configuration to activate
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
Converted AgentConfig ready for use
|
|
466
|
+
"""
|
|
467
|
+
try:
|
|
468
|
+
# Convert to standard configuration
|
|
469
|
+
agent_config = self.convert_custom_to_standard_config(custom_config)
|
|
470
|
+
|
|
471
|
+
# Apply permission overrides
|
|
472
|
+
self.apply_permission_overrides(custom_config)
|
|
473
|
+
|
|
474
|
+
# Update usage statistics
|
|
475
|
+
custom_config.increment_usage()
|
|
476
|
+
self.repository.update(custom_config)
|
|
477
|
+
|
|
478
|
+
# Track as active
|
|
479
|
+
self._active_custom_agent = custom_config
|
|
480
|
+
|
|
481
|
+
self.audit_logger.log_event(
|
|
482
|
+
AuditEventType.SYSTEM_EVENT,
|
|
483
|
+
AuditLevel.INFO,
|
|
484
|
+
f"Activated custom agent '{custom_config.name}'",
|
|
485
|
+
metadata={
|
|
486
|
+
"agent_id": custom_config.id,
|
|
487
|
+
"agent_name": custom_config.name,
|
|
488
|
+
"provider": custom_config.model_settings.provider_type.value,
|
|
489
|
+
"model": custom_config.model_settings.model_name,
|
|
490
|
+
"safety_level": custom_config.behavior_rules.safety_level,
|
|
491
|
+
},
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
logger.info(
|
|
495
|
+
f"Successfully activated custom agent: {custom_config.name} ({custom_config.id})"
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
return agent_config
|
|
499
|
+
|
|
500
|
+
except Exception as e:
|
|
501
|
+
logger.error(f"Failed to activate custom agent: {e}", exc_info=True)
|
|
502
|
+
self.audit_logger.log_event(
|
|
503
|
+
AuditEventType.SECURITY_ALERT,
|
|
504
|
+
AuditLevel.ERROR,
|
|
505
|
+
f"Failed to activate custom agent '{custom_config.name}': {e}",
|
|
506
|
+
metadata={"agent_id": custom_config.id, "error": str(e)},
|
|
507
|
+
)
|
|
508
|
+
raise
|
|
509
|
+
|
|
510
|
+
def deactivate_custom_agent(self) -> None:
|
|
511
|
+
"""Deactivate the currently active custom agent."""
|
|
512
|
+
if self._active_custom_agent:
|
|
513
|
+
agent_name = self._active_custom_agent.name
|
|
514
|
+
agent_id = self._active_custom_agent.id
|
|
515
|
+
|
|
516
|
+
# Clear cache
|
|
517
|
+
self._config_cache.pop(agent_id, None)
|
|
518
|
+
|
|
519
|
+
# Clear active agent
|
|
520
|
+
self._active_custom_agent = None
|
|
521
|
+
|
|
522
|
+
self.audit_logger.log_event(
|
|
523
|
+
AuditEventType.SYSTEM_EVENT,
|
|
524
|
+
AuditLevel.INFO,
|
|
525
|
+
f"Deactivated custom agent '{agent_name}'",
|
|
526
|
+
metadata={"agent_id": agent_id},
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
logger.info(f"Deactivated custom agent: {agent_name} ({agent_id})")
|
|
530
|
+
|
|
531
|
+
def get_active_custom_agent(self) -> Optional[CustomAgentConfig]:
|
|
532
|
+
"""Get the currently active custom agent."""
|
|
533
|
+
return self._active_custom_agent
|
|
534
|
+
|
|
535
|
+
def validate_custom_agent_security(
|
|
536
|
+
self, custom_config: CustomAgentConfig
|
|
537
|
+
) -> List[str]:
|
|
538
|
+
"""
|
|
539
|
+
Validate that custom agent configuration meets security requirements.
|
|
540
|
+
|
|
541
|
+
Args:
|
|
542
|
+
custom_config: Custom agent configuration to validate
|
|
543
|
+
|
|
544
|
+
Returns:
|
|
545
|
+
List of security warnings/issues (empty if valid)
|
|
546
|
+
"""
|
|
547
|
+
warnings = []
|
|
548
|
+
|
|
549
|
+
try:
|
|
550
|
+
# Check for dangerous tool combinations
|
|
551
|
+
if (
|
|
552
|
+
AgentTool.PROGRAM_EXECUTOR in custom_config.enabled_tools
|
|
553
|
+
and custom_config.behavior_rules.safety_level == "permissive"
|
|
554
|
+
):
|
|
555
|
+
warnings.append(
|
|
556
|
+
"Program executor with permissive safety level may be risky"
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
# Check for missing confirmation requirements
|
|
560
|
+
if (
|
|
561
|
+
AgentTool.FILE_OPERATIONS in custom_config.enabled_tools
|
|
562
|
+
and "file_delete"
|
|
563
|
+
not in custom_config.behavior_rules.require_confirmation_for
|
|
564
|
+
):
|
|
565
|
+
warnings.append(
|
|
566
|
+
"File operations enabled but file deletion doesn't require confirmation"
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
# Check system prompt for potentially dangerous instructions
|
|
570
|
+
system_prompt = custom_config.context_parameters.system_prompt.lower()
|
|
571
|
+
dangerous_phrases = [
|
|
572
|
+
"ignore safety",
|
|
573
|
+
"bypass security",
|
|
574
|
+
"disable approval",
|
|
575
|
+
"execute without asking",
|
|
576
|
+
"override permissions",
|
|
577
|
+
]
|
|
578
|
+
|
|
579
|
+
for phrase in dangerous_phrases:
|
|
580
|
+
if phrase in system_prompt:
|
|
581
|
+
warnings.append(
|
|
582
|
+
f"System prompt contains potentially dangerous phrase: '{phrase}'"
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
# Check model temperature for potentially unpredictable behavior
|
|
586
|
+
if custom_config.model_settings.temperature > 1.5:
|
|
587
|
+
warnings.append(
|
|
588
|
+
f"High temperature ({custom_config.model_settings.temperature}) may cause unpredictable behavior"
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
# Log validation results
|
|
592
|
+
if warnings:
|
|
593
|
+
self.audit_logger.log_event(
|
|
594
|
+
AuditEventType.SECURITY_ALERT,
|
|
595
|
+
AuditLevel.WARNING,
|
|
596
|
+
f"Security validation warnings for custom agent '{custom_config.name}'",
|
|
597
|
+
metadata={
|
|
598
|
+
"agent_id": custom_config.id,
|
|
599
|
+
"warnings": warnings,
|
|
600
|
+
"warning_count": len(warnings),
|
|
601
|
+
},
|
|
602
|
+
)
|
|
603
|
+
else:
|
|
604
|
+
self.audit_logger.log_event(
|
|
605
|
+
AuditEventType.SECURITY_ALERT,
|
|
606
|
+
AuditLevel.INFO,
|
|
607
|
+
f"Custom agent '{custom_config.name}' passed security validation",
|
|
608
|
+
metadata={"agent_id": custom_config.id},
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
return warnings
|
|
612
|
+
|
|
613
|
+
except Exception as e:
|
|
614
|
+
logger.error(f"Security validation error: {e}", exc_info=True)
|
|
615
|
+
return [f"Security validation error: {e}"]
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
# Utility functions for easy integration
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def create_custom_agent_integration(
|
|
622
|
+
repository: Optional[AgentRepository] = None,
|
|
623
|
+
permission_controller: Optional[PermissionController] = None,
|
|
624
|
+
) -> CustomAgentIntegration:
|
|
625
|
+
"""Create and initialize custom agent integration."""
|
|
626
|
+
return CustomAgentIntegration(
|
|
627
|
+
repository=repository, permission_controller=permission_controller
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def activate_custom_agent_by_id(
|
|
632
|
+
agent_id: str, integration: Optional[CustomAgentIntegration] = None
|
|
633
|
+
) -> Optional[AgentConfig]:
|
|
634
|
+
"""Activate a custom agent by ID."""
|
|
635
|
+
integration = integration or create_custom_agent_integration()
|
|
636
|
+
|
|
637
|
+
custom_config = integration.repository.get(agent_id)
|
|
638
|
+
if not custom_config:
|
|
639
|
+
return None
|
|
640
|
+
|
|
641
|
+
return integration.activate_custom_agent(custom_config)
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
def validate_agent_security(
|
|
645
|
+
agent_id: str, integration: Optional[CustomAgentIntegration] = None
|
|
646
|
+
) -> List[str]:
|
|
647
|
+
"""Validate security for a custom agent."""
|
|
648
|
+
integration = integration or create_custom_agent_integration()
|
|
649
|
+
|
|
650
|
+
custom_config = integration.repository.get(agent_id)
|
|
651
|
+
if not custom_config:
|
|
652
|
+
return ["Agent not found"]
|
|
653
|
+
|
|
654
|
+
return integration.validate_custom_agent_security(custom_config)
|