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.
Files changed (126) hide show
  1. omnimancer/__init__.py +42 -0
  2. omnimancer/__main__.py +9 -0
  3. omnimancer/cli/__init__.py +8 -0
  4. omnimancer/cli/agent_manager.py +826 -0
  5. omnimancer/cli/agent_wizard.py +944 -0
  6. omnimancer/cli/approval_formatter.py +734 -0
  7. omnimancer/cli/approval_integration.py +734 -0
  8. omnimancer/cli/approval_prompt.py +1286 -0
  9. omnimancer/cli/batch_approval_display.py +617 -0
  10. omnimancer/cli/batch_approval_filters.py +729 -0
  11. omnimancer/cli/batch_operation_monitor.py +775 -0
  12. omnimancer/cli/commands/performance_cmd.py +624 -0
  13. omnimancer/cli/commands.py +757 -0
  14. omnimancer/cli/completion_handler.py +281 -0
  15. omnimancer/cli/config_setup_wizard.py +783 -0
  16. omnimancer/cli/dynamic_commands.py +371 -0
  17. omnimancer/cli/handlers/__init__.py +18 -0
  18. omnimancer/cli/handlers/agent_handler.py +865 -0
  19. omnimancer/cli/handlers/agent_persona_handler.py +1048 -0
  20. omnimancer/cli/handlers/custom_agent_handler.py +352 -0
  21. omnimancer/cli/handlers/permissions_handler.py +1609 -0
  22. omnimancer/cli/interface.py +6695 -0
  23. omnimancer/cli/performance_dashboard.py +612 -0
  24. omnimancer/core/__init__.py +34 -0
  25. omnimancer/core/agent/__init__.py +256 -0
  26. omnimancer/core/agent/agent_config.py +715 -0
  27. omnimancer/core/agent/agent_switcher.py +668 -0
  28. omnimancer/core/agent/approval_context.py +460 -0
  29. omnimancer/core/agent/approval_dialog.py +902 -0
  30. omnimancer/core/agent/approval_interface.py +628 -0
  31. omnimancer/core/agent/approval_manager.py +760 -0
  32. omnimancer/core/agent/cli_integration.py +470 -0
  33. omnimancer/core/agent/config.py +845 -0
  34. omnimancer/core/agent/custom_agent_integration.py +654 -0
  35. omnimancer/core/agent/diff_renderer.py +706 -0
  36. omnimancer/core/agent/file_content_display.py +503 -0
  37. omnimancer/core/agent/file_modification_workflow.py +658 -0
  38. omnimancer/core/agent/file_system_manager.py +1790 -0
  39. omnimancer/core/agent/input_handler.py +614 -0
  40. omnimancer/core/agent/metrics_collector.py +771 -0
  41. omnimancer/core/agent/optimization_engine.py +729 -0
  42. omnimancer/core/agent/performance_monitor.py +717 -0
  43. omnimancer/core/agent/persona.py +870 -0
  44. omnimancer/core/agent/persona_validator.py +672 -0
  45. omnimancer/core/agent/program_executor.py +748 -0
  46. omnimancer/core/agent/proposed_changes_integration.py +663 -0
  47. omnimancer/core/agent/read_before_write_errors.py +492 -0
  48. omnimancer/core/agent/read_before_write_ui.py +647 -0
  49. omnimancer/core/agent/rich_renderer.py +763 -0
  50. omnimancer/core/agent/status_config.py +238 -0
  51. omnimancer/core/agent/status_core.py +446 -0
  52. omnimancer/core/agent/status_integrated_engine.py +540 -0
  53. omnimancer/core/agent/status_manager.py +878 -0
  54. omnimancer/core/agent/status_ui_components.py +535 -0
  55. omnimancer/core/agent/template_applicator.py +548 -0
  56. omnimancer/core/agent/terminal_status_listener.py +394 -0
  57. omnimancer/core/agent/token_tracker.py +679 -0
  58. omnimancer/core/agent/types.py +60 -0
  59. omnimancer/core/agent/web_client.py +745 -0
  60. omnimancer/core/agent/workflow_orchestrator.py +826 -0
  61. omnimancer/core/agent_engine.py +1625 -0
  62. omnimancer/core/agent_mode_manager.py +706 -0
  63. omnimancer/core/agent_progress_ui.py +545 -0
  64. omnimancer/core/chat_manager.py +141 -0
  65. omnimancer/core/config_manager.py +2199 -0
  66. omnimancer/core/config_migration.py +772 -0
  67. omnimancer/core/config_provider.py +1974 -0
  68. omnimancer/core/config_security_validator.py +393 -0
  69. omnimancer/core/config_validator.py +768 -0
  70. omnimancer/core/conversation_manager.py +352 -0
  71. omnimancer/core/engine.py +787 -0
  72. omnimancer/core/enhanced_input.py +523 -0
  73. omnimancer/core/env_loader.py +83 -0
  74. omnimancer/core/fallback_manager.py +568 -0
  75. omnimancer/core/health_monitor.py +462 -0
  76. omnimancer/core/history_manager.py +462 -0
  77. omnimancer/core/mcp_integration_layer.py +878 -0
  78. omnimancer/core/models.py +1889 -0
  79. omnimancer/core/provider_capabilities.py +403 -0
  80. omnimancer/core/provider_initializer.py +450 -0
  81. omnimancer/core/provider_registry.py +432 -0
  82. omnimancer/core/security/__init__.py +16 -0
  83. omnimancer/core/security/approval_workflow.py +406 -0
  84. omnimancer/core/security/audit_logger.py +511 -0
  85. omnimancer/core/security/permission_controller.py +511 -0
  86. omnimancer/core/security/sandbox_manager.py +379 -0
  87. omnimancer/core/security/security_manager.py +530 -0
  88. omnimancer/core/setup_wizard.py +345 -0
  89. omnimancer/core/setup_wizard_core.py +449 -0
  90. omnimancer/core/setup_wizard_guide_generator.py +376 -0
  91. omnimancer/core/setup_wizard_provider_setup.py +454 -0
  92. omnimancer/core/setup_wizard_ui.py +317 -0
  93. omnimancer/core/setup_wizard_validation.py +371 -0
  94. omnimancer/core/signal_handler.py +174 -0
  95. omnimancer/mcp/__init__.py +11 -0
  96. omnimancer/mcp/client.py +725 -0
  97. omnimancer/mcp/manager.py +649 -0
  98. omnimancer/providers/__init__.py +24 -0
  99. omnimancer/providers/azure.py +608 -0
  100. omnimancer/providers/base.py +262 -0
  101. omnimancer/providers/bedrock.py +711 -0
  102. omnimancer/providers/claude.py +426 -0
  103. omnimancer/providers/claude_code.py +406 -0
  104. omnimancer/providers/cohere.py +412 -0
  105. omnimancer/providers/factory.py +988 -0
  106. omnimancer/providers/gemini.py +708 -0
  107. omnimancer/providers/mistral.py +554 -0
  108. omnimancer/providers/ollama.py +510 -0
  109. omnimancer/providers/openai.py +362 -0
  110. omnimancer/providers/openrouter.py +709 -0
  111. omnimancer/providers/perplexity.py +476 -0
  112. omnimancer/providers/vertex.py +617 -0
  113. omnimancer/providers/xai.py +484 -0
  114. omnimancer/ui/__init__.py +6 -0
  115. omnimancer/ui/cancellation_handler.py +235 -0
  116. omnimancer/ui/progress_indicator.py +318 -0
  117. omnimancer/utils/__init__.py +22 -0
  118. omnimancer/utils/error_handler.py +589 -0
  119. omnimancer/utils/errors.py +667 -0
  120. omnimancer/utils/retry.py +238 -0
  121. omnimancer_cli-0.1.0.dist-info/METADATA +413 -0
  122. omnimancer_cli-0.1.0.dist-info/RECORD +126 -0
  123. omnimancer_cli-0.1.0.dist-info/WHEEL +5 -0
  124. omnimancer_cli-0.1.0.dist-info/entry_points.txt +4 -0
  125. omnimancer_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  126. 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)