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,865 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent CLI Handler for Omnimancer.
|
|
3
|
+
|
|
4
|
+
This module provides the AgentCLIHandler class that processes /agents commands
|
|
5
|
+
and coordinates with the agent engine to expose agent functionality to users.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import time
|
|
10
|
+
from typing import List, Optional
|
|
11
|
+
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
from rich.panel import Panel
|
|
14
|
+
from rich.prompt import Confirm
|
|
15
|
+
from rich.status import Status
|
|
16
|
+
from rich.table import Table
|
|
17
|
+
|
|
18
|
+
from ...core.agent.approval_manager import EnhancedApprovalManager
|
|
19
|
+
from ...core.agent.persona import (
|
|
20
|
+
PersonaManager,
|
|
21
|
+
PersonaStatus,
|
|
22
|
+
get_persona_manager,
|
|
23
|
+
)
|
|
24
|
+
from ...core.agent_engine import AgentEngine
|
|
25
|
+
from ...utils.errors import AgentError
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AgentError(Exception):
|
|
31
|
+
"""Agent-specific error."""
|
|
32
|
+
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class AgentNotFoundError(AgentError):
|
|
37
|
+
"""Agent not found error."""
|
|
38
|
+
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class PermissionDeniedError(AgentError):
|
|
43
|
+
"""Permission denied error."""
|
|
44
|
+
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class AgentBusyError(AgentError):
|
|
49
|
+
"""Agent is busy error."""
|
|
50
|
+
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ConfigurationError(AgentError):
|
|
55
|
+
"""Configuration error."""
|
|
56
|
+
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AgentCLIHandler:
|
|
61
|
+
"""
|
|
62
|
+
Handler class that processes /agents commands and coordinates with the agent engine.
|
|
63
|
+
|
|
64
|
+
This class serves as the bridge between CLI commands and the agent engine,
|
|
65
|
+
providing user-friendly interfaces for agent management.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(
|
|
69
|
+
self,
|
|
70
|
+
agent_engine: Optional[AgentEngine] = None,
|
|
71
|
+
approval_manager: Optional[EnhancedApprovalManager] = None,
|
|
72
|
+
console: Optional[Console] = None,
|
|
73
|
+
persona_manager: Optional[PersonaManager] = None,
|
|
74
|
+
verbose: bool = False,
|
|
75
|
+
):
|
|
76
|
+
"""
|
|
77
|
+
Initialize the agent CLI handler.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
agent_engine: Agent engine instance for coordination
|
|
81
|
+
approval_manager: Enhanced approval manager for permissions
|
|
82
|
+
console: Rich console for output formatting
|
|
83
|
+
persona_manager: Persona manager for agent personality management
|
|
84
|
+
verbose: Enable verbose logging and debugging output
|
|
85
|
+
"""
|
|
86
|
+
try:
|
|
87
|
+
self.agent_engine = agent_engine
|
|
88
|
+
self.approval_manager = approval_manager
|
|
89
|
+
self.console = console or Console()
|
|
90
|
+
self.verbose = verbose
|
|
91
|
+
|
|
92
|
+
# Initialize persona manager with error handling
|
|
93
|
+
try:
|
|
94
|
+
self.persona_manager = persona_manager or get_persona_manager()
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Failed to initialize PersonaManager: {e}")
|
|
97
|
+
if self.verbose:
|
|
98
|
+
self.console.print(
|
|
99
|
+
f"[yellow]Warning: PersonaManager initialization failed: {e}[/yellow]"
|
|
100
|
+
)
|
|
101
|
+
raise ConfigurationError(f"Failed to initialize persona system: {e}")
|
|
102
|
+
|
|
103
|
+
# Current agent tracking
|
|
104
|
+
self.current_agent = None
|
|
105
|
+
|
|
106
|
+
if self.verbose:
|
|
107
|
+
self.console.print(
|
|
108
|
+
"[dim]Agent CLI Handler initialized successfully[/dim]"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
except Exception as e:
|
|
112
|
+
logger.error(f"Failed to initialize AgentCLIHandler: {e}")
|
|
113
|
+
if console:
|
|
114
|
+
console.print(
|
|
115
|
+
f"[red]Error: Failed to initialize agent system: {e}[/red]"
|
|
116
|
+
)
|
|
117
|
+
raise ConfigurationError(f"Agent handler initialization failed: {e}")
|
|
118
|
+
|
|
119
|
+
async def handle_command(self, args: List[str]) -> None:
|
|
120
|
+
"""
|
|
121
|
+
Handle /agents command with subcommands.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
args: Command arguments from CLI parser
|
|
125
|
+
"""
|
|
126
|
+
if not args:
|
|
127
|
+
# Default to list if no subcommand provided
|
|
128
|
+
args = ["list"]
|
|
129
|
+
|
|
130
|
+
subcommand = args[0].lower()
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
if self.verbose:
|
|
134
|
+
self.console.print(
|
|
135
|
+
f"[dim]Executing agents subcommand: {subcommand}[/dim]"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if subcommand == "list":
|
|
139
|
+
await self.handle_list(args[1:] if len(args) > 1 else [])
|
|
140
|
+
elif subcommand == "enable":
|
|
141
|
+
await self.handle_enable(args[1:] if len(args) > 1 else [])
|
|
142
|
+
elif subcommand == "disable":
|
|
143
|
+
await self.handle_disable(args[1:] if len(args) > 1 else [])
|
|
144
|
+
elif subcommand == "status":
|
|
145
|
+
await self.handle_status(args[1:] if len(args) > 1 else [])
|
|
146
|
+
elif subcommand == "config":
|
|
147
|
+
await self.handle_config(args[1:] if len(args) > 1 else [])
|
|
148
|
+
elif subcommand == "switch":
|
|
149
|
+
await self.handle_switch(args[1:] if len(args) > 1 else [])
|
|
150
|
+
elif subcommand == "current":
|
|
151
|
+
await self.handle_current()
|
|
152
|
+
elif subcommand == "info":
|
|
153
|
+
await self.handle_info(args[1:] if len(args) > 1 else [])
|
|
154
|
+
else:
|
|
155
|
+
self._show_error_with_suggestions(
|
|
156
|
+
f"Unknown agents subcommand: '{subcommand}'",
|
|
157
|
+
f"Did you mean one of: list, enable, disable, status, config, switch, current, info?",
|
|
158
|
+
)
|
|
159
|
+
self._show_help()
|
|
160
|
+
|
|
161
|
+
except AgentNotFoundError as e:
|
|
162
|
+
logger.error(f"Agent not found: {e}")
|
|
163
|
+
self._show_error_with_suggestions(
|
|
164
|
+
str(e), "Use '/agents list' to see available agents."
|
|
165
|
+
)
|
|
166
|
+
except PermissionDeniedError as e:
|
|
167
|
+
logger.error(f"Permission denied: {e}")
|
|
168
|
+
self._show_error_with_suggestions(
|
|
169
|
+
f"Permission denied: {e}",
|
|
170
|
+
"Check your user permissions or contact an administrator.",
|
|
171
|
+
)
|
|
172
|
+
except AgentBusyError as e:
|
|
173
|
+
logger.error(f"Agent busy: {e}")
|
|
174
|
+
self._show_error_with_suggestions(
|
|
175
|
+
f"Agent is busy: {e}",
|
|
176
|
+
"Wait for the current operation to complete or use '/agents status' to check progress.",
|
|
177
|
+
)
|
|
178
|
+
except ConfigurationError as e:
|
|
179
|
+
logger.error(f"Configuration error: {e}")
|
|
180
|
+
self._show_error_with_suggestions(
|
|
181
|
+
f"Configuration error: {e}",
|
|
182
|
+
"Check your agent configuration and try again.",
|
|
183
|
+
)
|
|
184
|
+
except Exception as e:
|
|
185
|
+
logger.error(f"Agent command failed unexpectedly: {e}", exc_info=True)
|
|
186
|
+
self._show_error_with_suggestions(
|
|
187
|
+
f"Unexpected error occurred: {str(e)[:100]}{'...' if len(str(e)) > 100 else ''}",
|
|
188
|
+
"Try the command again or use '/agents status' to check system health.",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if self.verbose:
|
|
192
|
+
self.console.print(f"[dim]Full error details: {e}[/dim]")
|
|
193
|
+
|
|
194
|
+
async def handle_list(self, args: List[str]) -> None:
|
|
195
|
+
"""
|
|
196
|
+
Handle 'list' subcommand to show available agents.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
args: Additional arguments
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
table = Table(title="Available Agent Personas")
|
|
203
|
+
table.add_column("Agent ID", style="cyan", width=12)
|
|
204
|
+
table.add_column("Name", style="bold", width=18)
|
|
205
|
+
table.add_column("Description", style="white", width=40)
|
|
206
|
+
table.add_column("Provider", style="green", width=12)
|
|
207
|
+
table.add_column("Model", style="blue", width=25)
|
|
208
|
+
table.add_column("Status", style="yellow", width=10)
|
|
209
|
+
|
|
210
|
+
# Get personas from PersonaManager
|
|
211
|
+
personas = self.persona_manager.get_all_personas()
|
|
212
|
+
|
|
213
|
+
for agent_id, persona in personas.items():
|
|
214
|
+
# Map persona status to display
|
|
215
|
+
if persona.status == PersonaStatus.ACTIVE:
|
|
216
|
+
status = "🟢 Active"
|
|
217
|
+
elif persona.status == PersonaStatus.AVAILABLE:
|
|
218
|
+
status = "⚪ Available"
|
|
219
|
+
elif persona.status == PersonaStatus.DISABLED:
|
|
220
|
+
status = "🔴 Disabled"
|
|
221
|
+
elif persona.status == PersonaStatus.ERROR:
|
|
222
|
+
status = "❌ Error"
|
|
223
|
+
elif persona.status == PersonaStatus.LOADING:
|
|
224
|
+
status = "🔄 Loading"
|
|
225
|
+
else:
|
|
226
|
+
status = "❓ Unknown"
|
|
227
|
+
|
|
228
|
+
# Get provider info from configuration
|
|
229
|
+
config = persona.configuration
|
|
230
|
+
provider_name = (
|
|
231
|
+
config.provider_type.value if config.provider_type else "Unknown"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
table.add_row(
|
|
235
|
+
agent_id,
|
|
236
|
+
persona.name,
|
|
237
|
+
(
|
|
238
|
+
persona.description[:37] + "..."
|
|
239
|
+
if len(persona.description) > 40
|
|
240
|
+
else persona.description
|
|
241
|
+
),
|
|
242
|
+
provider_name,
|
|
243
|
+
config.model_id or "Unknown",
|
|
244
|
+
status,
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
self.console.print(table)
|
|
248
|
+
|
|
249
|
+
# Show current agent if any
|
|
250
|
+
active_persona = self.persona_manager.active_persona
|
|
251
|
+
if active_persona:
|
|
252
|
+
self.console.print(
|
|
253
|
+
f"\n[bold green]Current active agent:[/bold green] {active_persona.name} ({active_persona.id})"
|
|
254
|
+
)
|
|
255
|
+
else:
|
|
256
|
+
self.console.print(
|
|
257
|
+
f"\n[dim]No agent currently active. Use '/agents enable <agent_id>' to activate.[/dim]"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
except Exception as e:
|
|
261
|
+
self._show_error(f"Failed to list agents: {e}")
|
|
262
|
+
|
|
263
|
+
async def handle_enable(self, args: List[str]) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Handle 'enable' subcommand to activate an agent.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
args: Agent ID to enable
|
|
269
|
+
"""
|
|
270
|
+
if not args:
|
|
271
|
+
self._show_error_with_suggestions(
|
|
272
|
+
"Agent enable requires an agent ID.",
|
|
273
|
+
"Use '/agents list' to see available agents, then try '/agents enable <agent_id>'",
|
|
274
|
+
)
|
|
275
|
+
return
|
|
276
|
+
|
|
277
|
+
agent_id = args[0].lower()
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
if self.verbose:
|
|
281
|
+
self.console.print(
|
|
282
|
+
f"[dim]Checking if agent '{agent_id}' exists...[/dim]"
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Check if persona exists
|
|
286
|
+
persona = self.persona_manager.get_persona(agent_id)
|
|
287
|
+
if not persona:
|
|
288
|
+
# Suggest similar agents
|
|
289
|
+
available_agents = list(self.persona_manager.get_all_personas().keys())
|
|
290
|
+
suggestions = [
|
|
291
|
+
agent
|
|
292
|
+
for agent in available_agents
|
|
293
|
+
if agent_id in agent or agent in agent_id
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
if suggestions:
|
|
297
|
+
suggestion_text = f"Did you mean: {', '.join(suggestions)[:50]}?"
|
|
298
|
+
else:
|
|
299
|
+
suggestion_text = (
|
|
300
|
+
f"Available agents: {', '.join(available_agents)[:50]}..."
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
raise AgentNotFoundError(
|
|
304
|
+
f"Agent '{agent_id}' not found. {suggestion_text}"
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# Check if agent is already active
|
|
308
|
+
if persona.is_active:
|
|
309
|
+
self._show_info_with_action(
|
|
310
|
+
f"Agent '{agent_id}' is already active.",
|
|
311
|
+
f"Use '/agents status {agent_id}' to see details or '/agents disable {agent_id}' to deactivate.",
|
|
312
|
+
)
|
|
313
|
+
return
|
|
314
|
+
|
|
315
|
+
# Check permissions if approval manager is available
|
|
316
|
+
if self.approval_manager:
|
|
317
|
+
try:
|
|
318
|
+
# This would check if user has permission to enable agents
|
|
319
|
+
if not await self._check_permission_for_action(
|
|
320
|
+
"agent_enable", agent_id
|
|
321
|
+
):
|
|
322
|
+
raise PermissionDeniedError(
|
|
323
|
+
f"You don't have permission to enable agent '{agent_id}'"
|
|
324
|
+
)
|
|
325
|
+
except Exception as perm_e:
|
|
326
|
+
if self.verbose:
|
|
327
|
+
self.console.print(
|
|
328
|
+
f"[dim]Permission check failed: {perm_e}[/dim]"
|
|
329
|
+
)
|
|
330
|
+
# Continue if permission system is not available
|
|
331
|
+
|
|
332
|
+
# Show progress indicator for activation
|
|
333
|
+
with Status(
|
|
334
|
+
f"[bold blue]Activating {persona.name}...",
|
|
335
|
+
console=self.console,
|
|
336
|
+
):
|
|
337
|
+
if self.verbose:
|
|
338
|
+
self.console.print(
|
|
339
|
+
f"[dim]Calling PersonaManager.activate_persona('{agent_id}')...[/dim]"
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Small delay to show the spinner (activation is usually instant)
|
|
343
|
+
time.sleep(0.5)
|
|
344
|
+
|
|
345
|
+
# Activate the persona using PersonaManager
|
|
346
|
+
success = self.persona_manager.activate_persona(agent_id)
|
|
347
|
+
|
|
348
|
+
if not success:
|
|
349
|
+
raise ConfigurationError(
|
|
350
|
+
f"Failed to activate persona '{agent_id}'. Check system configuration."
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
# Update current agent tracking
|
|
354
|
+
self.current_agent = agent_id
|
|
355
|
+
|
|
356
|
+
# Show success message
|
|
357
|
+
config = persona.configuration
|
|
358
|
+
capabilities_list = [
|
|
359
|
+
cap.value.replace("_", " ").title() for cap in persona.capabilities
|
|
360
|
+
]
|
|
361
|
+
|
|
362
|
+
self.console.print(
|
|
363
|
+
Panel(
|
|
364
|
+
f"[bold green]Agent Enabled Successfully[/bold green]\n\n"
|
|
365
|
+
f"[bold]Agent:[/bold] {persona.name}\n"
|
|
366
|
+
f"[bold]Provider:[/bold] {config.provider_type.value if config.provider_type else 'Unknown'}\n"
|
|
367
|
+
f"[bold]Model:[/bold] {config.model_id or 'Unknown'}\n"
|
|
368
|
+
f"[bold]Capabilities:[/bold] {', '.join(capabilities_list)}\n\n"
|
|
369
|
+
f"The {persona.name} is now active and ready for use.\n"
|
|
370
|
+
f"Use '/agents status' to monitor or '/agents disable {agent_id}' to deactivate.",
|
|
371
|
+
title=f"✅ {persona.name} Active",
|
|
372
|
+
border_style="green",
|
|
373
|
+
)
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
except (AgentNotFoundError, PermissionDeniedError, ConfigurationError):
|
|
377
|
+
# These are handled by the main command handler
|
|
378
|
+
raise
|
|
379
|
+
except Exception as e:
|
|
380
|
+
logger.error(
|
|
381
|
+
f"Unexpected error enabling agent '{agent_id}': {e}",
|
|
382
|
+
exc_info=True,
|
|
383
|
+
)
|
|
384
|
+
raise ConfigurationError(f"Failed to enable agent '{agent_id}': {e}")
|
|
385
|
+
|
|
386
|
+
async def handle_disable(self, args: List[str]) -> None:
|
|
387
|
+
"""
|
|
388
|
+
Handle 'disable' subcommand to deactivate an agent.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
args: Agent ID to disable (optional if only one is active)
|
|
392
|
+
"""
|
|
393
|
+
try:
|
|
394
|
+
agent_id = None
|
|
395
|
+
persona = None
|
|
396
|
+
|
|
397
|
+
if args:
|
|
398
|
+
agent_id = args[0].lower()
|
|
399
|
+
if self.verbose:
|
|
400
|
+
self.console.print(f"[dim]Looking up agent '{agent_id}'...[/dim]")
|
|
401
|
+
|
|
402
|
+
persona = self.persona_manager.get_persona(agent_id)
|
|
403
|
+
if not persona:
|
|
404
|
+
available_agents = list(
|
|
405
|
+
self.persona_manager.get_all_personas().keys()
|
|
406
|
+
)
|
|
407
|
+
suggestions = [
|
|
408
|
+
agent
|
|
409
|
+
for agent in available_agents
|
|
410
|
+
if agent_id in agent or agent in agent_id
|
|
411
|
+
]
|
|
412
|
+
|
|
413
|
+
if suggestions:
|
|
414
|
+
suggestion_text = (
|
|
415
|
+
f"Did you mean: {', '.join(suggestions)[:50]}?"
|
|
416
|
+
)
|
|
417
|
+
else:
|
|
418
|
+
suggestion_text = f"Use '/agents list' to see available agents."
|
|
419
|
+
|
|
420
|
+
raise AgentNotFoundError(
|
|
421
|
+
f"Agent '{agent_id}' not found. {suggestion_text}"
|
|
422
|
+
)
|
|
423
|
+
else:
|
|
424
|
+
# Use currently active persona
|
|
425
|
+
if self.verbose:
|
|
426
|
+
self.console.print(
|
|
427
|
+
"[dim]Looking for currently active persona...[/dim]"
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
active_persona = self.persona_manager.active_persona
|
|
431
|
+
if active_persona:
|
|
432
|
+
agent_id = active_persona.id
|
|
433
|
+
persona = active_persona
|
|
434
|
+
else:
|
|
435
|
+
self._show_info_with_action(
|
|
436
|
+
"No agent is currently active.",
|
|
437
|
+
"Use '/agents list' to see available agents or '/agents enable <agent_id>' to activate one.",
|
|
438
|
+
)
|
|
439
|
+
return
|
|
440
|
+
|
|
441
|
+
if not persona.is_active:
|
|
442
|
+
self._show_info_with_action(
|
|
443
|
+
f"Agent '{agent_id}' is already disabled.",
|
|
444
|
+
f"Use '/agents enable {agent_id}' to activate it or '/agents list' to see active agents.",
|
|
445
|
+
)
|
|
446
|
+
return
|
|
447
|
+
|
|
448
|
+
# Check permissions if approval manager is available
|
|
449
|
+
if self.approval_manager:
|
|
450
|
+
try:
|
|
451
|
+
if not await self._check_permission_for_action(
|
|
452
|
+
"agent_disable", agent_id
|
|
453
|
+
):
|
|
454
|
+
raise PermissionDeniedError(
|
|
455
|
+
f"You don't have permission to disable agent '{agent_id}'"
|
|
456
|
+
)
|
|
457
|
+
except Exception as perm_e:
|
|
458
|
+
if self.verbose:
|
|
459
|
+
self.console.print(
|
|
460
|
+
f"[dim]Permission check failed: {perm_e}[/dim]"
|
|
461
|
+
)
|
|
462
|
+
# Continue if permission system is not available
|
|
463
|
+
|
|
464
|
+
# Check for active operations (placeholder - would integrate with agent engine)
|
|
465
|
+
active_operations = 0 # This would come from agent engine status
|
|
466
|
+
|
|
467
|
+
# Show confirmation prompt for destructive action
|
|
468
|
+
if active_operations > 0:
|
|
469
|
+
warning_msg = f"⚠️ Agent '{agent_id}' has {active_operations} active operations.\nDisabling will terminate these operations."
|
|
470
|
+
if not Confirm.ask(f"{warning_msg}\n\nDisable anyway?", default=False):
|
|
471
|
+
self._show_info("Agent remains enabled.")
|
|
472
|
+
return
|
|
473
|
+
elif not args: # Only confirm if no specific agent was provided
|
|
474
|
+
if not Confirm.ask(
|
|
475
|
+
f"Disable the active agent '{persona.name}'?", default=True
|
|
476
|
+
):
|
|
477
|
+
self._show_info("Agent remains enabled.")
|
|
478
|
+
return
|
|
479
|
+
|
|
480
|
+
# Show progress indicator for deactivation
|
|
481
|
+
with Status(
|
|
482
|
+
f"[bold red]Deactivating {persona.name}...",
|
|
483
|
+
console=self.console,
|
|
484
|
+
):
|
|
485
|
+
if self.verbose:
|
|
486
|
+
self.console.print(
|
|
487
|
+
f"[dim]Calling PersonaManager.deactivate_persona()...[/dim]"
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
# Small delay to show the spinner
|
|
491
|
+
time.sleep(0.3)
|
|
492
|
+
|
|
493
|
+
# Deactivate the persona using PersonaManager
|
|
494
|
+
success = self.persona_manager.deactivate_persona()
|
|
495
|
+
|
|
496
|
+
if not success:
|
|
497
|
+
raise ConfigurationError(
|
|
498
|
+
f"Failed to deactivate persona '{agent_id}'. Check system state."
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
# Update current agent tracking
|
|
502
|
+
if self.current_agent == agent_id:
|
|
503
|
+
self.current_agent = None
|
|
504
|
+
|
|
505
|
+
self.console.print(
|
|
506
|
+
Panel(
|
|
507
|
+
f"[bold red]Agent Disabled Successfully[/bold red]\n\n"
|
|
508
|
+
f"[bold]Agent:[/bold] {persona.name}\n"
|
|
509
|
+
f"All operations have been stopped.\n\n"
|
|
510
|
+
f"Use '/agents enable {agent_id}' to reactivate or '/agents list' to see other options.",
|
|
511
|
+
title=f"🔴 {persona.name} Disabled",
|
|
512
|
+
border_style="red",
|
|
513
|
+
)
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
except (AgentNotFoundError, PermissionDeniedError, ConfigurationError):
|
|
517
|
+
# These are handled by the main command handler
|
|
518
|
+
raise
|
|
519
|
+
except Exception as e:
|
|
520
|
+
logger.error(f"Unexpected error disabling agent: {e}", exc_info=True)
|
|
521
|
+
raise ConfigurationError(f"Failed to disable agent: {e}")
|
|
522
|
+
|
|
523
|
+
async def handle_status(self, args: List[str]) -> None:
|
|
524
|
+
"""
|
|
525
|
+
Handle 'status' subcommand to show agent status.
|
|
526
|
+
|
|
527
|
+
Args:
|
|
528
|
+
args: Optional agent ID for specific status
|
|
529
|
+
"""
|
|
530
|
+
try:
|
|
531
|
+
if args:
|
|
532
|
+
# Show specific agent status
|
|
533
|
+
agent_id = args[0].lower()
|
|
534
|
+
persona = self.persona_manager.get_persona(agent_id)
|
|
535
|
+
if not persona:
|
|
536
|
+
raise AgentNotFoundError(f"Agent '{agent_id}' not found")
|
|
537
|
+
|
|
538
|
+
# Map persona status to colors and text
|
|
539
|
+
status_mapping = {
|
|
540
|
+
PersonaStatus.ACTIVE: ("green", "Active"),
|
|
541
|
+
PersonaStatus.AVAILABLE: ("yellow", "Available"),
|
|
542
|
+
PersonaStatus.DISABLED: ("red", "Disabled"),
|
|
543
|
+
PersonaStatus.ERROR: ("red", "Error"),
|
|
544
|
+
PersonaStatus.LOADING: ("blue", "Loading"),
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
status_color, status_text = status_mapping.get(
|
|
548
|
+
persona.status, ("gray", "Unknown")
|
|
549
|
+
)
|
|
550
|
+
config = persona.configuration
|
|
551
|
+
capabilities_list = [
|
|
552
|
+
cap.value.replace("_", " ").title() for cap in persona.capabilities
|
|
553
|
+
]
|
|
554
|
+
|
|
555
|
+
self.console.print(
|
|
556
|
+
Panel(
|
|
557
|
+
f"[bold]Name:[/bold] {persona.name}\n"
|
|
558
|
+
f"[bold]Status:[/bold] [{status_color}]{status_text}[/{status_color}]\n"
|
|
559
|
+
f"[bold]Provider:[/bold] {config.provider_type.value if config.provider_type else 'Unknown'}\n"
|
|
560
|
+
f"[bold]Model:[/bold] {config.model_id or 'Unknown'}\n"
|
|
561
|
+
f"[bold]Description:[/bold] {persona.description}\n"
|
|
562
|
+
f"[bold]Capabilities:[/bold] {', '.join(capabilities_list)}\n",
|
|
563
|
+
title=f"Agent Status: {persona.name}",
|
|
564
|
+
border_style=status_color,
|
|
565
|
+
)
|
|
566
|
+
)
|
|
567
|
+
else:
|
|
568
|
+
# Show general agent status
|
|
569
|
+
personas = self.persona_manager.get_all_personas()
|
|
570
|
+
active_count = sum(1 for p in personas.values() if p.is_active)
|
|
571
|
+
total_count = len(personas)
|
|
572
|
+
|
|
573
|
+
status_text = f"[bold]Agent System Status[/bold]\n\n"
|
|
574
|
+
status_text += f"Available agents: {total_count}\n"
|
|
575
|
+
status_text += f"Active agents: {active_count}\n"
|
|
576
|
+
|
|
577
|
+
active_persona = self.persona_manager.active_persona
|
|
578
|
+
if active_persona:
|
|
579
|
+
status_text += f"Current active agent: {active_persona.name} ({active_persona.id})\n\n"
|
|
580
|
+
config = active_persona.configuration
|
|
581
|
+
status_text += f"[bold green]Active Agent Details:[/bold green]\n"
|
|
582
|
+
status_text += f"• Name: {active_persona.name}\n"
|
|
583
|
+
status_text += f"• Provider: {config.provider_type.value if config.provider_type else 'Unknown'}\n"
|
|
584
|
+
status_text += f"• Model: {config.model_id or 'Unknown'}\n"
|
|
585
|
+
else:
|
|
586
|
+
status_text += f"Current active agent: None\n\n"
|
|
587
|
+
status_text += f"[dim]Use '/agents enable <agent_id>' to activate an agent.[/dim]"
|
|
588
|
+
|
|
589
|
+
self.console.print(
|
|
590
|
+
Panel(
|
|
591
|
+
status_text,
|
|
592
|
+
title="🤖 Agent System Status",
|
|
593
|
+
border_style="blue",
|
|
594
|
+
)
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
except AgentNotFoundError as e:
|
|
598
|
+
self._show_error(str(e))
|
|
599
|
+
except Exception as e:
|
|
600
|
+
self._show_error(f"Failed to get agent status: {e}")
|
|
601
|
+
|
|
602
|
+
async def handle_config(self, args: List[str]) -> None:
|
|
603
|
+
"""
|
|
604
|
+
Handle 'config' subcommand to view/modify agent settings.
|
|
605
|
+
|
|
606
|
+
Args:
|
|
607
|
+
args: Agent ID and optional config parameters
|
|
608
|
+
"""
|
|
609
|
+
if not args:
|
|
610
|
+
self._show_error(
|
|
611
|
+
"Config command requires an agent ID. Use '/agents list' to see available agents."
|
|
612
|
+
)
|
|
613
|
+
return
|
|
614
|
+
|
|
615
|
+
agent_id = args[0].lower()
|
|
616
|
+
|
|
617
|
+
try:
|
|
618
|
+
persona = self.persona_manager.get_persona(agent_id)
|
|
619
|
+
if not persona:
|
|
620
|
+
raise AgentNotFoundError(f"Agent '{agent_id}' not found")
|
|
621
|
+
|
|
622
|
+
config = persona.configuration
|
|
623
|
+
capabilities_list = [
|
|
624
|
+
cap.value.replace("_", " ").title() for cap in persona.capabilities
|
|
625
|
+
]
|
|
626
|
+
status_text = (
|
|
627
|
+
"Active"
|
|
628
|
+
if persona.is_active
|
|
629
|
+
else (
|
|
630
|
+
"Available"
|
|
631
|
+
if persona.status == PersonaStatus.AVAILABLE
|
|
632
|
+
else persona.status.value.title()
|
|
633
|
+
)
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
# For now, just show current configuration
|
|
637
|
+
# In the future, this would allow modifying settings
|
|
638
|
+
self.console.print(
|
|
639
|
+
Panel(
|
|
640
|
+
f"[bold]Configuration for {persona.name}[/bold]\n\n"
|
|
641
|
+
f"[bold]Provider:[/bold] {config.provider_type.value if config.provider_type else 'Unknown'}\n"
|
|
642
|
+
f"[bold]Model:[/bold] {config.model_id or 'Unknown'}\n"
|
|
643
|
+
f"[bold]Temperature:[/bold] {config.temperature if config.temperature is not None else 'Default'}\n"
|
|
644
|
+
f"[bold]Max Tokens:[/bold] {config.max_tokens or 'Default'}\n"
|
|
645
|
+
f"[bold]Tools Enabled:[/bold] {'Yes' if config.tools_enabled else 'No'}\n"
|
|
646
|
+
f"[bold]Web Search:[/bold] {'Yes' if config.web_search_enabled else 'No'}\n"
|
|
647
|
+
f"[bold]File Operations:[/bold] {'Yes' if config.file_operations_enabled else 'No'}\n"
|
|
648
|
+
f"[bold]Approval Required:[/bold] {'Yes' if config.approval_required else 'No'}\n"
|
|
649
|
+
f"[bold]Capabilities:[/bold] {', '.join(capabilities_list)}\n"
|
|
650
|
+
f"[bold]Status:[/bold] {status_text}\n\n"
|
|
651
|
+
f"[dim]Configuration editing will be available in future versions.[/dim]",
|
|
652
|
+
title=f"⚙️ {persona.name} Configuration",
|
|
653
|
+
border_style="cyan",
|
|
654
|
+
)
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
except AgentNotFoundError as e:
|
|
658
|
+
self._show_error(str(e))
|
|
659
|
+
except Exception as e:
|
|
660
|
+
self._show_error(f"Failed to show agent config: {e}")
|
|
661
|
+
|
|
662
|
+
async def handle_switch(self, args: List[str]) -> None:
|
|
663
|
+
"""
|
|
664
|
+
Handle 'switch' subcommand to switch between agents.
|
|
665
|
+
|
|
666
|
+
Args:
|
|
667
|
+
args: Agent ID to switch to
|
|
668
|
+
"""
|
|
669
|
+
if not args:
|
|
670
|
+
self._show_error(
|
|
671
|
+
"Switch command requires an agent ID. Use '/agents list' to see available agents."
|
|
672
|
+
)
|
|
673
|
+
return
|
|
674
|
+
|
|
675
|
+
# Switch is essentially disable current + enable new
|
|
676
|
+
await self.handle_enable(args)
|
|
677
|
+
|
|
678
|
+
async def handle_current(self) -> None:
|
|
679
|
+
"""Handle 'current' subcommand to show currently active agent."""
|
|
680
|
+
active_persona = self.persona_manager.active_persona
|
|
681
|
+
if active_persona:
|
|
682
|
+
config = active_persona.configuration
|
|
683
|
+
self.console.print(
|
|
684
|
+
f"[bold green]Current active agent:[/bold green] {active_persona.name} ({active_persona.id})"
|
|
685
|
+
)
|
|
686
|
+
self.console.print(
|
|
687
|
+
f"[bold]Provider:[/bold] {config.provider_type.value if config.provider_type else 'Unknown'}"
|
|
688
|
+
)
|
|
689
|
+
self.console.print(f"[bold]Model:[/bold] {config.model_id or 'Unknown'}")
|
|
690
|
+
else:
|
|
691
|
+
self.console.print("[dim]No agent is currently active.[/dim]")
|
|
692
|
+
|
|
693
|
+
async def handle_info(self, args: List[str]) -> None:
|
|
694
|
+
"""
|
|
695
|
+
Handle 'info' subcommand to show detailed agent information.
|
|
696
|
+
|
|
697
|
+
Args:
|
|
698
|
+
args: Agent ID to get info for
|
|
699
|
+
"""
|
|
700
|
+
if not args:
|
|
701
|
+
self._show_error(
|
|
702
|
+
"Info command requires an agent ID. Use '/agents list' to see available agents."
|
|
703
|
+
)
|
|
704
|
+
return
|
|
705
|
+
|
|
706
|
+
agent_id = args[0].lower()
|
|
707
|
+
|
|
708
|
+
try:
|
|
709
|
+
persona = self.persona_manager.get_persona(agent_id)
|
|
710
|
+
if not persona:
|
|
711
|
+
raise AgentNotFoundError(f"Agent '{agent_id}' not found")
|
|
712
|
+
|
|
713
|
+
config = persona.configuration
|
|
714
|
+
capabilities_list = [
|
|
715
|
+
cap.value.replace("_", " ").title() for cap in persona.capabilities
|
|
716
|
+
]
|
|
717
|
+
|
|
718
|
+
# Get status with appropriate emoji
|
|
719
|
+
if persona.is_active:
|
|
720
|
+
status_display = "🟢 Active"
|
|
721
|
+
elif persona.status == PersonaStatus.AVAILABLE:
|
|
722
|
+
status_display = "⚪ Available"
|
|
723
|
+
elif persona.status == PersonaStatus.DISABLED:
|
|
724
|
+
status_display = "🔴 Disabled"
|
|
725
|
+
elif persona.status == PersonaStatus.ERROR:
|
|
726
|
+
status_display = "❌ Error"
|
|
727
|
+
elif persona.status == PersonaStatus.LOADING:
|
|
728
|
+
status_display = "🔄 Loading"
|
|
729
|
+
else:
|
|
730
|
+
status_display = f"❓ {persona.status.value.title()}"
|
|
731
|
+
|
|
732
|
+
info_text = f"[bold]{persona.name}[/bold]\n\n"
|
|
733
|
+
info_text += f"[bold]Description:[/bold] {persona.description}\n\n"
|
|
734
|
+
info_text += f"[bold]Technical Details:[/bold]\n"
|
|
735
|
+
info_text += f"• Provider: {config.provider_type.value if config.provider_type else 'Unknown'}\n"
|
|
736
|
+
info_text += f"• Model: {config.model_id or 'Unknown'}\n"
|
|
737
|
+
info_text += f"• Temperature: {config.temperature if config.temperature is not None else 'Default'}\n"
|
|
738
|
+
info_text += f"• Max Tokens: {config.max_tokens or 'Default'}\n"
|
|
739
|
+
info_text += f"• Status: {status_display}\n\n"
|
|
740
|
+
info_text += f"[bold]Capabilities:[/bold]\n"
|
|
741
|
+
for capability in capabilities_list:
|
|
742
|
+
info_text += f"• {capability}\n"
|
|
743
|
+
|
|
744
|
+
info_text += f"\n[bold]Settings:[/bold]\n"
|
|
745
|
+
info_text += f"• Tools Enabled: {'Yes' if config.tools_enabled else 'No'}\n"
|
|
746
|
+
info_text += (
|
|
747
|
+
f"• Web Search: {'Yes' if config.web_search_enabled else 'No'}\n"
|
|
748
|
+
)
|
|
749
|
+
info_text += f"• File Operations: {'Yes' if config.file_operations_enabled else 'No'}\n"
|
|
750
|
+
info_text += (
|
|
751
|
+
f"• Approval Required: {'Yes' if config.approval_required else 'No'}\n"
|
|
752
|
+
)
|
|
753
|
+
|
|
754
|
+
info_text += f"\n[bold]Usage:[/bold]\n"
|
|
755
|
+
info_text += f"• Enable: [cyan]/agents enable {agent_id}[/cyan]\n"
|
|
756
|
+
info_text += f"• Disable: [cyan]/agents disable {agent_id}[/cyan]\n"
|
|
757
|
+
info_text += f"• Status: [cyan]/agents status {agent_id}[/cyan]\n"
|
|
758
|
+
|
|
759
|
+
self.console.print(
|
|
760
|
+
Panel(
|
|
761
|
+
info_text,
|
|
762
|
+
title=f"ℹ️ {persona.name} Information",
|
|
763
|
+
border_style="blue",
|
|
764
|
+
)
|
|
765
|
+
)
|
|
766
|
+
|
|
767
|
+
except AgentNotFoundError as e:
|
|
768
|
+
self._show_error(str(e))
|
|
769
|
+
except Exception as e:
|
|
770
|
+
self._show_error(f"Failed to show agent info: {e}")
|
|
771
|
+
|
|
772
|
+
def _show_help(self) -> None:
|
|
773
|
+
"""Show help for agents command."""
|
|
774
|
+
help_text = """[bold]Agent Commands:[/bold]
|
|
775
|
+
|
|
776
|
+
[cyan]/agents list[/cyan] - List all available agent personas
|
|
777
|
+
[cyan]/agents enable <agent_id>[/cyan] - Enable/activate an agent persona
|
|
778
|
+
[cyan]/agents disable [agent_id][/cyan] - Disable active agent
|
|
779
|
+
[cyan]/agents switch <agent_id>[/cyan] - Switch to different agent persona
|
|
780
|
+
[cyan]/agents status [agent_id][/cyan] - Show agent status (general or specific)
|
|
781
|
+
[cyan]/agents current[/cyan] - Show currently active agent
|
|
782
|
+
[cyan]/agents config <agent_id>[/cyan] - View agent configuration
|
|
783
|
+
[cyan]/agents info <agent_id>[/cyan] - Show detailed agent information
|
|
784
|
+
|
|
785
|
+
[bold]Available Agent Types:[/bold]
|
|
786
|
+
• [green]coding[/green] - Development-focused with Claude Sonnet + dev tools
|
|
787
|
+
• [blue]research[/blue] - Research-oriented with Perplexity + web search
|
|
788
|
+
• [magenta]creative[/magenta] - Creative writing with high-temperature models
|
|
789
|
+
• [yellow]performance[/yellow] - Fast and cost-efficient with optimized models
|
|
790
|
+
• [cyan]general[/cyan] - Balanced general-purpose configuration
|
|
791
|
+
|
|
792
|
+
[bold]Examples:[/bold]
|
|
793
|
+
[cyan]/agents enable coding[/cyan] - Activate the coding agent
|
|
794
|
+
[cyan]/agents status[/cyan] - Show overall agent system status
|
|
795
|
+
[cyan]/agents info research[/cyan] - Get details about the research agent"""
|
|
796
|
+
|
|
797
|
+
self.console.print(
|
|
798
|
+
Panel(
|
|
799
|
+
help_text,
|
|
800
|
+
title="🤖 Agent Management Help",
|
|
801
|
+
border_style="blue",
|
|
802
|
+
)
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
def _show_error(self, message: str) -> None:
|
|
806
|
+
"""Show error message."""
|
|
807
|
+
self.console.print(f"[bold red]Error:[/bold red] {message}")
|
|
808
|
+
|
|
809
|
+
def _show_error_with_suggestions(self, error_message: str, suggestion: str) -> None:
|
|
810
|
+
"""Show error message with actionable suggestions."""
|
|
811
|
+
self.console.print(
|
|
812
|
+
Panel(
|
|
813
|
+
f"[bold red]Error:[/bold red] {error_message}\n\n"
|
|
814
|
+
f"[bold]Suggestion:[/bold] {suggestion}",
|
|
815
|
+
title="❌ Error",
|
|
816
|
+
border_style="red",
|
|
817
|
+
)
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
def _show_info(self, message: str) -> None:
|
|
821
|
+
"""Show info message."""
|
|
822
|
+
self.console.print(f"[blue]Info:[/blue] {message}")
|
|
823
|
+
|
|
824
|
+
def _show_info_with_action(self, info_message: str, action: str) -> None:
|
|
825
|
+
"""Show info message with suggested action."""
|
|
826
|
+
self.console.print(
|
|
827
|
+
Panel(
|
|
828
|
+
f"[blue]Info:[/blue] {info_message}\n\n"
|
|
829
|
+
f"[bold]Next Steps:[/bold] {action}",
|
|
830
|
+
title="ℹ️ Information",
|
|
831
|
+
border_style="blue",
|
|
832
|
+
)
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
def _show_success(self, message: str) -> None:
|
|
836
|
+
"""Show success message."""
|
|
837
|
+
self.console.print(f"[bold green]Success:[/bold green] {message}")
|
|
838
|
+
|
|
839
|
+
async def _check_permission_for_action(self, action: str, target: str) -> bool:
|
|
840
|
+
"""
|
|
841
|
+
Check if user has permission for a specific action.
|
|
842
|
+
|
|
843
|
+
Args:
|
|
844
|
+
action: The action being attempted (e.g., 'agent_enable', 'agent_disable')
|
|
845
|
+
target: The target of the action (e.g., agent_id)
|
|
846
|
+
|
|
847
|
+
Returns:
|
|
848
|
+
True if permission is granted, False otherwise
|
|
849
|
+
"""
|
|
850
|
+
try:
|
|
851
|
+
if not self.approval_manager:
|
|
852
|
+
return True # No approval manager means no restrictions
|
|
853
|
+
|
|
854
|
+
# This would integrate with the EnhancedApprovalManager
|
|
855
|
+
# For now, we'll assume all actions are permitted
|
|
856
|
+
if self.verbose:
|
|
857
|
+
self.console.print(
|
|
858
|
+
f"[dim]Checking permission for action '{action}' on target '{target}'[/dim]"
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
return True # Placeholder - would implement real permission checking
|
|
862
|
+
|
|
863
|
+
except Exception as e:
|
|
864
|
+
logger.error(f"Permission check failed for action '{action}': {e}")
|
|
865
|
+
return True # Fail open for now
|