code-puppy 0.0.302__py3-none-any.whl → 0.0.323__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.
- code_puppy/agents/base_agent.py +373 -46
- code_puppy/chatgpt_codex_client.py +283 -0
- code_puppy/cli_runner.py +795 -0
- code_puppy/command_line/add_model_menu.py +8 -1
- code_puppy/command_line/autosave_menu.py +266 -35
- code_puppy/command_line/colors_menu.py +515 -0
- code_puppy/command_line/command_handler.py +8 -2
- code_puppy/command_line/config_commands.py +59 -10
- code_puppy/command_line/core_commands.py +19 -7
- code_puppy/command_line/mcp/edit_command.py +3 -1
- code_puppy/command_line/mcp/handler.py +7 -2
- code_puppy/command_line/mcp/install_command.py +8 -3
- code_puppy/command_line/mcp/logs_command.py +173 -64
- code_puppy/command_line/mcp/restart_command.py +7 -2
- code_puppy/command_line/mcp/search_command.py +10 -4
- code_puppy/command_line/mcp/start_all_command.py +16 -6
- code_puppy/command_line/mcp/start_command.py +3 -1
- code_puppy/command_line/mcp/status_command.py +2 -1
- code_puppy/command_line/mcp/stop_all_command.py +5 -1
- code_puppy/command_line/mcp/stop_command.py +3 -1
- code_puppy/command_line/mcp/wizard_utils.py +10 -4
- code_puppy/command_line/model_settings_menu.py +53 -7
- code_puppy/command_line/prompt_toolkit_completion.py +16 -2
- code_puppy/command_line/session_commands.py +11 -4
- code_puppy/config.py +103 -15
- code_puppy/keymap.py +8 -2
- code_puppy/main.py +5 -828
- code_puppy/mcp_/__init__.py +17 -0
- code_puppy/mcp_/blocking_startup.py +61 -32
- code_puppy/mcp_/config_wizard.py +5 -1
- code_puppy/mcp_/managed_server.py +23 -3
- code_puppy/mcp_/manager.py +65 -0
- code_puppy/mcp_/mcp_logs.py +224 -0
- code_puppy/messaging/__init__.py +20 -4
- code_puppy/messaging/bus.py +64 -0
- code_puppy/messaging/markdown_patches.py +57 -0
- code_puppy/messaging/messages.py +16 -0
- code_puppy/messaging/renderers.py +21 -9
- code_puppy/messaging/rich_renderer.py +113 -67
- code_puppy/messaging/spinner/console_spinner.py +34 -0
- code_puppy/model_factory.py +185 -30
- code_puppy/model_utils.py +57 -48
- code_puppy/models.json +19 -5
- code_puppy/plugins/chatgpt_oauth/config.py +5 -1
- code_puppy/plugins/chatgpt_oauth/oauth_flow.py +5 -6
- code_puppy/plugins/chatgpt_oauth/register_callbacks.py +3 -3
- code_puppy/plugins/chatgpt_oauth/test_plugin.py +26 -11
- code_puppy/plugins/chatgpt_oauth/utils.py +180 -65
- code_puppy/plugins/claude_code_oauth/register_callbacks.py +28 -0
- code_puppy/plugins/claude_code_oauth/utils.py +1 -0
- code_puppy/plugins/shell_safety/agent_shell_safety.py +1 -118
- code_puppy/plugins/shell_safety/register_callbacks.py +44 -3
- code_puppy/prompts/codex_system_prompt.md +310 -0
- code_puppy/pydantic_patches.py +131 -0
- code_puppy/terminal_utils.py +126 -0
- code_puppy/tools/agent_tools.py +34 -9
- code_puppy/tools/command_runner.py +361 -32
- code_puppy/tools/file_operations.py +33 -45
- {code_puppy-0.0.302.data → code_puppy-0.0.323.data}/data/code_puppy/models.json +19 -5
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.323.dist-info}/METADATA +1 -1
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.323.dist-info}/RECORD +65 -57
- {code_puppy-0.0.302.data → code_puppy-0.0.323.data}/data/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.323.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.323.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.323.dist-info}/licenses/LICENSE +0 -0
|
@@ -145,6 +145,8 @@ def handle_exit_command(command: str) -> bool:
|
|
|
145
145
|
)
|
|
146
146
|
def handle_agent_command(command: str) -> bool:
|
|
147
147
|
"""Handle agent switching."""
|
|
148
|
+
from rich.text import Text
|
|
149
|
+
|
|
148
150
|
from code_puppy.agents import (
|
|
149
151
|
get_agent_descriptions,
|
|
150
152
|
get_available_agents,
|
|
@@ -201,7 +203,9 @@ def handle_agent_command(command: str) -> bool:
|
|
|
201
203
|
)
|
|
202
204
|
emit_info(f"{new_agent.description}", message_group=group_id)
|
|
203
205
|
emit_info(
|
|
204
|
-
|
|
206
|
+
Text.from_markup(
|
|
207
|
+
f"[dim]Auto-save session rotated to: {new_session_id}[/dim]"
|
|
208
|
+
),
|
|
205
209
|
message_group=group_id,
|
|
206
210
|
)
|
|
207
211
|
else:
|
|
@@ -224,15 +228,19 @@ def handle_agent_command(command: str) -> bool:
|
|
|
224
228
|
group_id = str(uuid.uuid4())
|
|
225
229
|
|
|
226
230
|
emit_info(
|
|
227
|
-
|
|
231
|
+
Text.from_markup(
|
|
232
|
+
f"[bold green]Current Agent:[/bold green] {current_agent.display_name}"
|
|
233
|
+
),
|
|
228
234
|
message_group=group_id,
|
|
229
235
|
)
|
|
230
236
|
emit_info(
|
|
231
|
-
f"[dim]{current_agent.description}[/dim]\n",
|
|
237
|
+
Text.from_markup(f"[dim]{current_agent.description}[/dim]\n"),
|
|
238
|
+
message_group=group_id,
|
|
232
239
|
)
|
|
233
240
|
|
|
234
241
|
emit_info(
|
|
235
|
-
"[bold magenta]Available Agents:[/bold magenta]",
|
|
242
|
+
Text.from_markup("[bold magenta]Available Agents:[/bold magenta]"),
|
|
243
|
+
message_group=group_id,
|
|
236
244
|
)
|
|
237
245
|
for name, display_name in available_agents.items():
|
|
238
246
|
description = descriptions.get(name, "No description")
|
|
@@ -240,13 +248,15 @@ def handle_agent_command(command: str) -> bool:
|
|
|
240
248
|
" [green]← current[/green]" if name == current_agent.name else ""
|
|
241
249
|
)
|
|
242
250
|
emit_info(
|
|
243
|
-
|
|
251
|
+
Text.from_markup(
|
|
252
|
+
f" [cyan]{name:<12}[/cyan] {display_name}{current_marker}"
|
|
253
|
+
),
|
|
244
254
|
message_group=group_id,
|
|
245
255
|
)
|
|
246
256
|
emit_info(f" {description}", message_group=group_id)
|
|
247
257
|
|
|
248
258
|
emit_info(
|
|
249
|
-
"\n[yellow]Usage:[/yellow] /agent <agent-name>",
|
|
259
|
+
Text.from_markup("\n[yellow]Usage:[/yellow] /agent <agent-name>"),
|
|
250
260
|
message_group=group_id,
|
|
251
261
|
)
|
|
252
262
|
return True
|
|
@@ -292,7 +302,9 @@ def handle_agent_command(command: str) -> bool:
|
|
|
292
302
|
)
|
|
293
303
|
emit_info(f"{new_agent.description}", message_group=group_id)
|
|
294
304
|
emit_info(
|
|
295
|
-
|
|
305
|
+
Text.from_markup(
|
|
306
|
+
f"[dim]Auto-save session rotated to: {new_session_id}[/dim]"
|
|
307
|
+
),
|
|
296
308
|
message_group=group_id,
|
|
297
309
|
)
|
|
298
310
|
return True
|
|
@@ -8,6 +8,8 @@ import logging
|
|
|
8
8
|
import os
|
|
9
9
|
from typing import List, Optional
|
|
10
10
|
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
11
13
|
from code_puppy.config import MCP_SERVERS_FILE
|
|
12
14
|
from code_puppy.messaging import emit_error, emit_info, emit_warning
|
|
13
15
|
|
|
@@ -39,7 +41,7 @@ class EditCommand(MCPCommandBase):
|
|
|
39
41
|
# Need a server name
|
|
40
42
|
if not args:
|
|
41
43
|
emit_info(
|
|
42
|
-
"[yellow]Usage: /mcp edit <server_name>[/yellow]",
|
|
44
|
+
Text.from_markup("[yellow]Usage: /mcp edit <server_name>[/yellow]"),
|
|
43
45
|
message_group=group_id,
|
|
44
46
|
)
|
|
45
47
|
emit_info(
|
|
@@ -8,6 +8,8 @@ to their respective command modules.
|
|
|
8
8
|
import logging
|
|
9
9
|
import shlex
|
|
10
10
|
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
11
13
|
from code_puppy.messaging import emit_info
|
|
12
14
|
|
|
13
15
|
from .add_command import AddCommand
|
|
@@ -103,7 +105,8 @@ class MCPCommandHandler(MCPCommandBase):
|
|
|
103
105
|
args = shlex.split(args_str)
|
|
104
106
|
except ValueError as e:
|
|
105
107
|
emit_info(
|
|
106
|
-
f"[red]Invalid command syntax: {e}[/red]",
|
|
108
|
+
Text.from_markup(f"[red]Invalid command syntax: {e}[/red]"),
|
|
109
|
+
message_group=group_id,
|
|
107
110
|
)
|
|
108
111
|
return True
|
|
109
112
|
|
|
@@ -121,7 +124,9 @@ class MCPCommandHandler(MCPCommandBase):
|
|
|
121
124
|
return True
|
|
122
125
|
else:
|
|
123
126
|
emit_info(
|
|
124
|
-
|
|
127
|
+
Text.from_markup(
|
|
128
|
+
f"[yellow]Unknown MCP subcommand: {subcommand}[/yellow]"
|
|
129
|
+
),
|
|
125
130
|
message_group=group_id,
|
|
126
131
|
)
|
|
127
132
|
emit_info(
|
|
@@ -5,6 +5,8 @@ MCP Install Command - Installs pre-configured MCP servers from the registry.
|
|
|
5
5
|
import logging
|
|
6
6
|
from typing import List, Optional
|
|
7
7
|
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
|
|
8
10
|
from code_puppy.messaging import emit_error, emit_info
|
|
9
11
|
|
|
10
12
|
from .base import MCPCommandBase
|
|
@@ -150,7 +152,9 @@ class InstallCommand(MCPCommandBase):
|
|
|
150
152
|
required_env_vars = selected_server.get_environment_vars()
|
|
151
153
|
if required_env_vars:
|
|
152
154
|
emit_info(
|
|
153
|
-
|
|
155
|
+
Text.from_markup(
|
|
156
|
+
"\n[yellow]Required Environment Variables:[/yellow]"
|
|
157
|
+
),
|
|
154
158
|
message_group=group_id,
|
|
155
159
|
)
|
|
156
160
|
for var in required_env_vars:
|
|
@@ -160,7 +164,7 @@ class InstallCommand(MCPCommandBase):
|
|
|
160
164
|
current_value = os.environ.get(var, "")
|
|
161
165
|
if current_value:
|
|
162
166
|
emit_info(
|
|
163
|
-
f" {var}: [green]Already set[/green]",
|
|
167
|
+
Text.from_markup(f" {var}: [green]Already set[/green]"),
|
|
164
168
|
message_group=group_id,
|
|
165
169
|
)
|
|
166
170
|
env_vars[var] = current_value
|
|
@@ -173,7 +177,8 @@ class InstallCommand(MCPCommandBase):
|
|
|
173
177
|
required_cmd_args = selected_server.get_command_line_args()
|
|
174
178
|
if required_cmd_args:
|
|
175
179
|
emit_info(
|
|
176
|
-
"\n[yellow]Command Line Arguments:[/yellow]",
|
|
180
|
+
Text.from_markup("\n[yellow]Command Line Arguments:[/yellow]"),
|
|
181
|
+
message_group=group_id,
|
|
177
182
|
)
|
|
178
183
|
for arg_config in required_cmd_args:
|
|
179
184
|
name = arg_config.get("name", "")
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
"""
|
|
2
|
-
MCP Logs Command - Shows
|
|
2
|
+
MCP Logs Command - Shows server logs from persistent log files.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
-
from datetime import datetime
|
|
7
6
|
from typing import List, Optional
|
|
8
7
|
|
|
9
|
-
from rich.
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.syntax import Syntax
|
|
10
10
|
from rich.text import Text
|
|
11
11
|
|
|
12
|
+
from code_puppy.mcp_.mcp_logs import (
|
|
13
|
+
clear_logs,
|
|
14
|
+
get_log_file_path,
|
|
15
|
+
get_log_stats,
|
|
16
|
+
list_servers_with_logs,
|
|
17
|
+
read_logs,
|
|
18
|
+
)
|
|
12
19
|
from code_puppy.messaging import emit_error, emit_info
|
|
13
20
|
|
|
14
21
|
from .base import MCPCommandBase
|
|
@@ -22,105 +29,207 @@ class LogsCommand(MCPCommandBase):
|
|
|
22
29
|
"""
|
|
23
30
|
Command handler for showing MCP server logs.
|
|
24
31
|
|
|
25
|
-
Shows
|
|
32
|
+
Shows logs from persistent log files stored in ~/.code_puppy/mcp_logs/.
|
|
26
33
|
"""
|
|
27
34
|
|
|
28
35
|
def execute(self, args: List[str], group_id: Optional[str] = None) -> None:
|
|
29
36
|
"""
|
|
30
|
-
Show
|
|
37
|
+
Show logs for a server.
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
/mcp logs - List servers with logs
|
|
41
|
+
/mcp logs <server_name> - Show last 50 lines
|
|
42
|
+
/mcp logs <server_name> 100 - Show last 100 lines
|
|
43
|
+
/mcp logs <server_name> all - Show all logs
|
|
44
|
+
/mcp logs <server_name> --clear - Clear logs for server
|
|
31
45
|
|
|
32
46
|
Args:
|
|
33
|
-
args: Command arguments
|
|
47
|
+
args: Command arguments
|
|
34
48
|
group_id: Optional message group ID for grouping related messages
|
|
35
49
|
"""
|
|
36
50
|
if group_id is None:
|
|
37
51
|
group_id = self.generate_group_id()
|
|
38
52
|
|
|
53
|
+
# No args - list servers with logs
|
|
39
54
|
if not args:
|
|
40
|
-
|
|
55
|
+
self._list_servers_with_logs(group_id)
|
|
41
56
|
return
|
|
42
57
|
|
|
43
58
|
server_name = args[0]
|
|
44
|
-
|
|
59
|
+
|
|
60
|
+
# Check for --clear flag
|
|
61
|
+
if len(args) > 1 and args[1] == "--clear":
|
|
62
|
+
self._clear_logs(server_name, group_id)
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
# Determine number of lines
|
|
66
|
+
lines = 50 # Default
|
|
67
|
+
show_all = False
|
|
45
68
|
|
|
46
69
|
if len(args) > 1:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
70
|
+
if args[1].lower() == "all":
|
|
71
|
+
show_all = True
|
|
72
|
+
else:
|
|
73
|
+
try:
|
|
74
|
+
lines = int(args[1])
|
|
75
|
+
if lines <= 0:
|
|
76
|
+
emit_info(
|
|
77
|
+
"Lines must be positive, using default: 50",
|
|
78
|
+
message_group=group_id,
|
|
79
|
+
)
|
|
80
|
+
lines = 50
|
|
81
|
+
except ValueError:
|
|
50
82
|
emit_info(
|
|
51
|
-
"
|
|
83
|
+
f"Invalid number '{args[1]}', using default: 50",
|
|
52
84
|
message_group=group_id,
|
|
53
85
|
)
|
|
54
|
-
limit = 10
|
|
55
|
-
except ValueError:
|
|
56
|
-
emit_info(
|
|
57
|
-
f"Invalid limit '{args[1]}', using default: 10",
|
|
58
|
-
message_group=group_id,
|
|
59
|
-
)
|
|
60
86
|
|
|
87
|
+
self._show_logs(server_name, lines if not show_all else None, group_id)
|
|
88
|
+
|
|
89
|
+
def _list_servers_with_logs(self, group_id: str) -> None:
|
|
90
|
+
"""List all servers that have log files."""
|
|
91
|
+
servers = list_servers_with_logs()
|
|
92
|
+
|
|
93
|
+
if not servers:
|
|
94
|
+
emit_info(
|
|
95
|
+
"📋 No MCP server logs found.\n"
|
|
96
|
+
"Logs are created when servers are started.",
|
|
97
|
+
message_group=group_id,
|
|
98
|
+
)
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
lines = ["📋 **Servers with logs:**\n"]
|
|
102
|
+
|
|
103
|
+
for server in servers:
|
|
104
|
+
stats = get_log_stats(server)
|
|
105
|
+
size_kb = stats["total_size_bytes"] / 1024
|
|
106
|
+
size_str = (
|
|
107
|
+
f"{size_kb:.1f} KB" if size_kb < 1024 else f"{size_kb / 1024:.1f} MB"
|
|
108
|
+
)
|
|
109
|
+
rotated = (
|
|
110
|
+
f" (+{stats['rotated_count']} rotated)"
|
|
111
|
+
if stats["rotated_count"]
|
|
112
|
+
else ""
|
|
113
|
+
)
|
|
114
|
+
lines.append(
|
|
115
|
+
f" • **{server}** - {stats['line_count']} lines, {size_str}{rotated}"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
lines.append("\n**Usage:** `/mcp logs <server_name> [lines|all]`")
|
|
119
|
+
|
|
120
|
+
emit_info("\n".join(lines), message_group=group_id)
|
|
121
|
+
|
|
122
|
+
def _show_logs(self, server_name: str, lines: Optional[int], group_id: str) -> None:
|
|
123
|
+
"""
|
|
124
|
+
Show logs for a specific server.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
server_name: Name of the server
|
|
128
|
+
lines: Number of lines to show, or None for all
|
|
129
|
+
group_id: Message group ID
|
|
130
|
+
"""
|
|
61
131
|
try:
|
|
62
|
-
#
|
|
132
|
+
# Verify server exists in manager
|
|
63
133
|
server_id = find_server_id_by_name(self.manager, server_name)
|
|
64
134
|
if not server_id:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
135
|
+
# Server not configured, but might have logs from before
|
|
136
|
+
stats = get_log_stats(server_name)
|
|
137
|
+
if not stats["exists"]:
|
|
138
|
+
emit_info(
|
|
139
|
+
f"Server '{server_name}' not found and has no logs.",
|
|
140
|
+
message_group=group_id,
|
|
141
|
+
)
|
|
142
|
+
suggest_similar_servers(
|
|
143
|
+
self.manager, server_name, group_id=group_id
|
|
144
|
+
)
|
|
145
|
+
return
|
|
68
146
|
|
|
69
|
-
#
|
|
70
|
-
|
|
147
|
+
# Read logs
|
|
148
|
+
log_lines = read_logs(server_name, lines=lines)
|
|
71
149
|
|
|
72
|
-
if not
|
|
150
|
+
if not log_lines:
|
|
73
151
|
emit_info(
|
|
74
|
-
f"
|
|
152
|
+
f"📋 No logs found for server: **{server_name}**\n"
|
|
153
|
+
f"Log file: `{get_log_file_path(server_name)}`",
|
|
75
154
|
message_group=group_id,
|
|
76
155
|
)
|
|
77
156
|
return
|
|
78
157
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
158
|
+
# Get stats for header
|
|
159
|
+
stats = get_log_stats(server_name)
|
|
160
|
+
total_lines = stats["line_count"]
|
|
161
|
+
showing = len(log_lines)
|
|
162
|
+
|
|
163
|
+
# Format header
|
|
164
|
+
if lines is None:
|
|
165
|
+
header = f"📋 Logs for {server_name} (all {total_lines} lines)"
|
|
166
|
+
else:
|
|
167
|
+
header = (
|
|
168
|
+
f"📋 Logs for {server_name} (last {showing} of {total_lines} lines)"
|
|
85
169
|
)
|
|
86
|
-
return
|
|
87
170
|
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
171
|
+
# Format log content with syntax highlighting
|
|
172
|
+
log_content = "\n".join(log_lines)
|
|
173
|
+
|
|
174
|
+
# Create a panel with the logs
|
|
175
|
+
syntax = Syntax(
|
|
176
|
+
log_content,
|
|
177
|
+
"log",
|
|
178
|
+
theme="monokai",
|
|
179
|
+
word_wrap=True,
|
|
180
|
+
line_numbers=False,
|
|
181
|
+
)
|
|
93
182
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
183
|
+
panel = Panel(
|
|
184
|
+
syntax,
|
|
185
|
+
title=header,
|
|
186
|
+
subtitle=f"Log file: {get_log_file_path(server_name)}",
|
|
187
|
+
border_style="dim",
|
|
97
188
|
)
|
|
98
189
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# Color code event types
|
|
111
|
-
event_style = "cyan"
|
|
112
|
-
if "error" in event_type.lower():
|
|
113
|
-
event_style = "red"
|
|
114
|
-
elif event_type in ["started", "enabled", "registered"]:
|
|
115
|
-
event_style = "green"
|
|
116
|
-
elif event_type in ["stopped", "disabled"]:
|
|
117
|
-
event_style = "yellow"
|
|
118
|
-
|
|
119
|
-
table.add_row(
|
|
120
|
-
time_str, Text(event_type, style=event_style), details_str or "-"
|
|
190
|
+
emit_info(panel, message_group=group_id)
|
|
191
|
+
|
|
192
|
+
# Show hint for more options
|
|
193
|
+
if lines is not None and showing < total_lines:
|
|
194
|
+
emit_info(
|
|
195
|
+
Text.from_markup(
|
|
196
|
+
f"[dim]💡 Use `/mcp logs {server_name} all` to see all logs, "
|
|
197
|
+
f"or `/mcp logs {server_name} <number>` for specific count[/dim]"
|
|
198
|
+
),
|
|
199
|
+
message_group=group_id,
|
|
121
200
|
)
|
|
122
|
-
emit_info(table, message_group=group_id)
|
|
123
201
|
|
|
124
202
|
except Exception as e:
|
|
125
203
|
logger.error(f"Error getting logs for server '{server_name}': {e}")
|
|
126
204
|
emit_error(f"Error getting logs: {e}", message_group=group_id)
|
|
205
|
+
|
|
206
|
+
def _clear_logs(self, server_name: str, group_id: str) -> None:
|
|
207
|
+
"""
|
|
208
|
+
Clear logs for a specific server.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
server_name: Name of the server
|
|
212
|
+
group_id: Message group ID
|
|
213
|
+
"""
|
|
214
|
+
try:
|
|
215
|
+
stats = get_log_stats(server_name)
|
|
216
|
+
|
|
217
|
+
if not stats["exists"] and stats["rotated_count"] == 0:
|
|
218
|
+
emit_info(
|
|
219
|
+
f"No logs to clear for server: {server_name}",
|
|
220
|
+
message_group=group_id,
|
|
221
|
+
)
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
# Clear the logs
|
|
225
|
+
clear_logs(server_name, include_rotated=True)
|
|
226
|
+
|
|
227
|
+
cleared_count = 1 + stats["rotated_count"]
|
|
228
|
+
emit_info(
|
|
229
|
+
f"🗑️ Cleared {cleared_count} log file(s) for **{server_name}**",
|
|
230
|
+
message_group=group_id,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
except Exception as e:
|
|
234
|
+
logger.error(f"Error clearing logs for server '{server_name}': {e}")
|
|
235
|
+
emit_error(f"Error clearing logs: {e}", message_group=group_id)
|
|
@@ -5,6 +5,8 @@ MCP Restart Command - Restarts a specific MCP server.
|
|
|
5
5
|
import logging
|
|
6
6
|
from typing import List, Optional
|
|
7
7
|
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
|
|
8
10
|
from code_puppy.messaging import emit_info
|
|
9
11
|
|
|
10
12
|
from .base import MCPCommandBase
|
|
@@ -72,7 +74,9 @@ class RestartCommand(MCPCommandBase):
|
|
|
72
74
|
# Update MCP tool cache immediately so token counts reflect the change
|
|
73
75
|
agent.update_mcp_tool_cache_sync()
|
|
74
76
|
emit_info(
|
|
75
|
-
|
|
77
|
+
Text.from_markup(
|
|
78
|
+
"[dim]Agent reloaded with updated servers[/dim]"
|
|
79
|
+
),
|
|
76
80
|
message_group=group_id,
|
|
77
81
|
)
|
|
78
82
|
except Exception as e:
|
|
@@ -91,5 +95,6 @@ class RestartCommand(MCPCommandBase):
|
|
|
91
95
|
except Exception as e:
|
|
92
96
|
logger.error(f"Error restarting server '{server_name}': {e}")
|
|
93
97
|
emit_info(
|
|
94
|
-
f"[red]Failed to restart server: {e}[/red]",
|
|
98
|
+
Text.from_markup(f"[red]Failed to restart server: {e}[/red]"),
|
|
99
|
+
message_group=group_id,
|
|
95
100
|
)
|
|
@@ -6,6 +6,7 @@ import logging
|
|
|
6
6
|
from typing import List, Optional
|
|
7
7
|
|
|
8
8
|
from rich.table import Table
|
|
9
|
+
from rich.text import Text
|
|
9
10
|
|
|
10
11
|
from code_puppy.messaging import emit_info, emit_system_message, emit_warning
|
|
11
12
|
|
|
@@ -99,19 +100,24 @@ class SearchCommand(MCPCommandBase):
|
|
|
99
100
|
emit_system_message(table, message_group=group_id)
|
|
100
101
|
emit_info("\n✓ = Verified ⭐ = Popular", message_group=group_id)
|
|
101
102
|
emit_info(
|
|
102
|
-
"[yellow]To install:[/yellow] /mcp install <id>",
|
|
103
|
+
Text.from_markup("[yellow]To install:[/yellow] /mcp install <id>"),
|
|
104
|
+
message_group=group_id,
|
|
103
105
|
)
|
|
104
106
|
emit_info(
|
|
105
|
-
|
|
107
|
+
Text.from_markup(
|
|
108
|
+
"[yellow]For details:[/yellow] /mcp search <specific-term>"
|
|
109
|
+
),
|
|
106
110
|
message_group=group_id,
|
|
107
111
|
)
|
|
108
112
|
|
|
109
113
|
except ImportError:
|
|
110
114
|
emit_info(
|
|
111
|
-
"[red]Server registry not available[/red]",
|
|
115
|
+
Text.from_markup("[red]Server registry not available[/red]"),
|
|
116
|
+
message_group=group_id,
|
|
112
117
|
)
|
|
113
118
|
except Exception as e:
|
|
114
119
|
logger.error(f"Error searching server registry: {e}")
|
|
115
120
|
emit_info(
|
|
116
|
-
f"[red]Error searching servers: {e}[/red]",
|
|
121
|
+
Text.from_markup(f"[red]Error searching servers: {e}[/red]"),
|
|
122
|
+
message_group=group_id,
|
|
117
123
|
)
|
|
@@ -6,6 +6,8 @@ import logging
|
|
|
6
6
|
import time
|
|
7
7
|
from typing import List, Optional
|
|
8
8
|
|
|
9
|
+
from rich.text import Text
|
|
10
|
+
|
|
9
11
|
from code_puppy.mcp_.managed_server import ServerState
|
|
10
12
|
from code_puppy.messaging import emit_info
|
|
11
13
|
|
|
@@ -67,20 +69,23 @@ class StartAllCommand(MCPCommandBase):
|
|
|
67
69
|
if success:
|
|
68
70
|
started_count += 1
|
|
69
71
|
emit_info(
|
|
70
|
-
f" [green]✓ Started: {server_name}[/green]",
|
|
72
|
+
Text.from_markup(f" [green]✓ Started: {server_name}[/green]"),
|
|
71
73
|
message_group=group_id,
|
|
72
74
|
)
|
|
73
75
|
else:
|
|
74
76
|
failed_count += 1
|
|
75
77
|
emit_info(
|
|
76
|
-
f" [red]✗ Failed: {server_name}[/red]",
|
|
78
|
+
Text.from_markup(f" [red]✗ Failed: {server_name}[/red]"),
|
|
79
|
+
message_group=group_id,
|
|
77
80
|
)
|
|
78
81
|
|
|
79
82
|
# Summary
|
|
80
83
|
emit_info("", message_group=group_id)
|
|
81
84
|
if started_count > 0:
|
|
82
85
|
emit_info(
|
|
83
|
-
|
|
86
|
+
Text.from_markup(
|
|
87
|
+
f"[green]Started {started_count} server(s)[/green]"
|
|
88
|
+
),
|
|
84
89
|
message_group=group_id,
|
|
85
90
|
)
|
|
86
91
|
if already_running > 0:
|
|
@@ -90,7 +95,9 @@ class StartAllCommand(MCPCommandBase):
|
|
|
90
95
|
)
|
|
91
96
|
if failed_count > 0:
|
|
92
97
|
emit_info(
|
|
93
|
-
|
|
98
|
+
Text.from_markup(
|
|
99
|
+
f"[yellow]Failed to start {failed_count} server(s)[/yellow]"
|
|
100
|
+
),
|
|
94
101
|
message_group=group_id,
|
|
95
102
|
)
|
|
96
103
|
|
|
@@ -112,7 +119,9 @@ class StartAllCommand(MCPCommandBase):
|
|
|
112
119
|
# Update MCP tool cache immediately so token counts reflect the change
|
|
113
120
|
agent.update_mcp_tool_cache_sync()
|
|
114
121
|
emit_info(
|
|
115
|
-
|
|
122
|
+
Text.from_markup(
|
|
123
|
+
"[dim]Agent reloaded with updated servers[/dim]"
|
|
124
|
+
),
|
|
116
125
|
message_group=group_id,
|
|
117
126
|
)
|
|
118
127
|
except Exception as e:
|
|
@@ -121,5 +130,6 @@ class StartAllCommand(MCPCommandBase):
|
|
|
121
130
|
except Exception as e:
|
|
122
131
|
logger.error(f"Error starting all servers: {e}")
|
|
123
132
|
emit_info(
|
|
124
|
-
f"[red]Failed to start servers: {e}[/red]",
|
|
133
|
+
Text.from_markup(f"[red]Failed to start servers: {e}[/red]"),
|
|
134
|
+
message_group=group_id,
|
|
125
135
|
)
|
|
@@ -6,6 +6,8 @@ import logging
|
|
|
6
6
|
import time
|
|
7
7
|
from typing import List, Optional
|
|
8
8
|
|
|
9
|
+
from rich.text import Text
|
|
10
|
+
|
|
9
11
|
from code_puppy.messaging import emit_error, emit_info, emit_success
|
|
10
12
|
|
|
11
13
|
from ...agents import get_current_agent
|
|
@@ -36,7 +38,7 @@ class StartCommand(MCPCommandBase):
|
|
|
36
38
|
|
|
37
39
|
if not args:
|
|
38
40
|
emit_info(
|
|
39
|
-
"[yellow]Usage: /mcp start <server_name>[/yellow]",
|
|
41
|
+
Text.from_markup("[yellow]Usage: /mcp start <server_name>[/yellow]"),
|
|
40
42
|
message_group=group_id,
|
|
41
43
|
)
|
|
42
44
|
return
|
|
@@ -7,6 +7,7 @@ from datetime import datetime
|
|
|
7
7
|
from typing import List, Optional
|
|
8
8
|
|
|
9
9
|
from rich.panel import Panel
|
|
10
|
+
from rich.text import Text
|
|
10
11
|
|
|
11
12
|
from code_puppy.mcp_.managed_server import ServerState
|
|
12
13
|
from code_puppy.messaging import emit_error, emit_info
|
|
@@ -158,7 +159,7 @@ class StatusCommand(MCPCommandBase):
|
|
|
158
159
|
status_lines.append(f"[bold]Metadata:[/bold] {len(metadata)} keys")
|
|
159
160
|
|
|
160
161
|
# Create and show the panel
|
|
161
|
-
panel_content = "\n".join(status_lines)
|
|
162
|
+
panel_content = Text.from_markup("\n".join(status_lines))
|
|
162
163
|
panel = Panel(
|
|
163
164
|
panel_content, title=f"🔌 {server_name} Status", border_style="cyan"
|
|
164
165
|
)
|
|
@@ -6,6 +6,8 @@ import logging
|
|
|
6
6
|
import time
|
|
7
7
|
from typing import List, Optional
|
|
8
8
|
|
|
9
|
+
from rich.text import Text
|
|
10
|
+
|
|
9
11
|
from code_puppy.mcp_.managed_server import ServerState
|
|
10
12
|
from code_puppy.messaging import emit_info
|
|
11
13
|
|
|
@@ -97,7 +99,9 @@ class StopAllCommand(MCPCommandBase):
|
|
|
97
99
|
# Update MCP tool cache immediately so token counts reflect the change
|
|
98
100
|
agent.update_mcp_tool_cache_sync()
|
|
99
101
|
emit_info(
|
|
100
|
-
|
|
102
|
+
Text.from_markup(
|
|
103
|
+
"[dim]Agent reloaded with updated servers[/dim]"
|
|
104
|
+
),
|
|
101
105
|
message_group=group_id,
|
|
102
106
|
)
|
|
103
107
|
except Exception as e:
|
|
@@ -5,6 +5,8 @@ MCP Stop Command - Stops a specific MCP server.
|
|
|
5
5
|
import logging
|
|
6
6
|
from typing import List, Optional
|
|
7
7
|
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
|
|
8
10
|
from code_puppy.messaging import emit_error, emit_info
|
|
9
11
|
|
|
10
12
|
from ...agents import get_current_agent
|
|
@@ -35,7 +37,7 @@ class StopCommand(MCPCommandBase):
|
|
|
35
37
|
|
|
36
38
|
if not args:
|
|
37
39
|
emit_info(
|
|
38
|
-
"[yellow]Usage: /mcp stop <server_name>[/yellow]",
|
|
40
|
+
Text.from_markup("[yellow]Usage: /mcp stop <server_name>[/yellow]"),
|
|
39
41
|
message_group=group_id,
|
|
40
42
|
)
|
|
41
43
|
return
|