code-puppy 0.0.287__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/__init__.py +3 -1
- code_puppy/agents/agent_code_puppy.py +5 -4
- code_puppy/agents/agent_creator_agent.py +22 -18
- code_puppy/agents/agent_manager.py +2 -2
- code_puppy/agents/base_agent.py +496 -102
- code_puppy/callbacks.py +8 -0
- code_puppy/chatgpt_codex_client.py +283 -0
- code_puppy/cli_runner.py +795 -0
- code_puppy/command_line/add_model_menu.py +19 -16
- code_puppy/command_line/attachments.py +10 -5
- code_puppy/command_line/autosave_menu.py +269 -41
- code_puppy/command_line/colors_menu.py +515 -0
- code_puppy/command_line/command_handler.py +10 -24
- code_puppy/command_line/config_commands.py +106 -25
- code_puppy/command_line/core_commands.py +32 -20
- code_puppy/command_line/mcp/add_command.py +3 -16
- code_puppy/command_line/mcp/base.py +0 -3
- code_puppy/command_line/mcp/catalog_server_installer.py +15 -15
- code_puppy/command_line/mcp/custom_server_form.py +66 -5
- code_puppy/command_line/mcp/custom_server_installer.py +17 -17
- code_puppy/command_line/mcp/edit_command.py +15 -22
- code_puppy/command_line/mcp/handler.py +7 -2
- code_puppy/command_line/mcp/help_command.py +2 -2
- code_puppy/command_line/mcp/install_command.py +10 -14
- code_puppy/command_line/mcp/install_menu.py +2 -6
- code_puppy/command_line/mcp/list_command.py +2 -2
- code_puppy/command_line/mcp/logs_command.py +174 -65
- code_puppy/command_line/mcp/remove_command.py +2 -2
- code_puppy/command_line/mcp/restart_command.py +7 -2
- code_puppy/command_line/mcp/search_command.py +16 -10
- code_puppy/command_line/mcp/start_all_command.py +16 -6
- code_puppy/command_line/mcp/start_command.py +12 -10
- code_puppy/command_line/mcp/status_command.py +4 -5
- code_puppy/command_line/mcp/stop_all_command.py +5 -1
- code_puppy/command_line/mcp/stop_command.py +6 -4
- code_puppy/command_line/mcp/test_command.py +2 -2
- code_puppy/command_line/mcp/wizard_utils.py +20 -16
- code_puppy/command_line/model_settings_menu.py +53 -7
- code_puppy/command_line/motd.py +1 -1
- code_puppy/command_line/pin_command_completion.py +82 -7
- code_puppy/command_line/prompt_toolkit_completion.py +32 -9
- code_puppy/command_line/session_commands.py +11 -4
- code_puppy/config.py +217 -53
- code_puppy/error_logging.py +118 -0
- code_puppy/gemini_code_assist.py +385 -0
- code_puppy/keymap.py +126 -0
- code_puppy/main.py +5 -745
- code_puppy/mcp_/__init__.py +17 -0
- code_puppy/mcp_/blocking_startup.py +63 -36
- code_puppy/mcp_/captured_stdio_server.py +1 -1
- code_puppy/mcp_/config_wizard.py +4 -4
- code_puppy/mcp_/dashboard.py +15 -6
- code_puppy/mcp_/managed_server.py +25 -5
- code_puppy/mcp_/manager.py +65 -0
- code_puppy/mcp_/mcp_logs.py +224 -0
- code_puppy/mcp_/registry.py +6 -6
- code_puppy/messaging/__init__.py +184 -2
- code_puppy/messaging/bus.py +610 -0
- code_puppy/messaging/commands.py +167 -0
- code_puppy/messaging/markdown_patches.py +57 -0
- code_puppy/messaging/message_queue.py +3 -3
- code_puppy/messaging/messages.py +470 -0
- code_puppy/messaging/renderers.py +43 -141
- code_puppy/messaging/rich_renderer.py +900 -0
- code_puppy/messaging/spinner/console_spinner.py +39 -2
- code_puppy/model_factory.py +292 -53
- code_puppy/model_utils.py +57 -48
- code_puppy/models.json +19 -5
- code_puppy/plugins/__init__.py +152 -10
- code_puppy/plugins/chatgpt_oauth/config.py +20 -12
- 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 +30 -13
- code_puppy/plugins/chatgpt_oauth/utils.py +180 -65
- code_puppy/plugins/claude_code_oauth/config.py +15 -11
- code_puppy/plugins/claude_code_oauth/register_callbacks.py +28 -0
- code_puppy/plugins/claude_code_oauth/utils.py +6 -1
- code_puppy/plugins/example_custom_command/register_callbacks.py +2 -2
- code_puppy/plugins/oauth_puppy_html.py +3 -0
- code_puppy/plugins/shell_safety/agent_shell_safety.py +1 -134
- code_puppy/plugins/shell_safety/command_cache.py +156 -0
- code_puppy/plugins/shell_safety/register_callbacks.py +77 -3
- code_puppy/prompts/codex_system_prompt.md +310 -0
- code_puppy/pydantic_patches.py +131 -0
- code_puppy/session_storage.py +2 -1
- code_puppy/status_display.py +7 -5
- code_puppy/terminal_utils.py +126 -0
- code_puppy/tools/agent_tools.py +131 -70
- code_puppy/tools/browser/browser_control.py +10 -14
- code_puppy/tools/browser/browser_interactions.py +20 -28
- code_puppy/tools/browser/browser_locators.py +27 -29
- code_puppy/tools/browser/browser_navigation.py +9 -9
- code_puppy/tools/browser/browser_screenshot.py +12 -14
- code_puppy/tools/browser/browser_scripts.py +17 -29
- code_puppy/tools/browser/browser_workflows.py +24 -25
- code_puppy/tools/browser/camoufox_manager.py +22 -26
- code_puppy/tools/command_runner.py +410 -88
- code_puppy/tools/common.py +51 -38
- code_puppy/tools/file_modifications.py +98 -24
- code_puppy/tools/file_operations.py +113 -202
- code_puppy/version_checker.py +28 -13
- {code_puppy-0.0.287.data → code_puppy-0.0.323.data}/data/code_puppy/models.json +19 -5
- {code_puppy-0.0.287.dist-info → code_puppy-0.0.323.dist-info}/METADATA +3 -8
- code_puppy-0.0.323.dist-info/RECORD +168 -0
- code_puppy/tui_state.py +0 -55
- code_puppy-0.0.287.dist-info/RECORD +0 -153
- {code_puppy-0.0.287.data → code_puppy-0.0.323.data}/data/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.287.dist-info → code_puppy-0.0.323.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.287.dist-info → code_puppy-0.0.323.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.287.dist-info → code_puppy-0.0.323.dist-info}/licenses/LICENSE +0 -0
|
@@ -25,6 +25,7 @@ from prompt_toolkit.lexers import PygmentsLexer
|
|
|
25
25
|
from prompt_toolkit.widgets import Frame, TextArea
|
|
26
26
|
from pygments.lexers.data import JsonLexer
|
|
27
27
|
|
|
28
|
+
from code_puppy.messaging import emit_info, emit_success
|
|
28
29
|
from code_puppy.tools.command_runner import set_awaiting_user_input
|
|
29
30
|
|
|
30
31
|
# Example configurations for each server type
|
|
@@ -106,6 +107,10 @@ class CustomServerForm:
|
|
|
106
107
|
# Focus state: 0=name, 1=type, 2=json
|
|
107
108
|
self.focused_field = 0
|
|
108
109
|
|
|
110
|
+
# Status message for user feedback (e.g., "Save failed: ...")
|
|
111
|
+
self.status_message: Optional[str] = None
|
|
112
|
+
self.status_is_error: bool = False
|
|
113
|
+
|
|
109
114
|
# Result
|
|
110
115
|
self.result = None # "installed", "cancelled", None
|
|
111
116
|
|
|
@@ -136,6 +141,12 @@ class CustomServerForm:
|
|
|
136
141
|
else:
|
|
137
142
|
name_display = self.server_name if self.server_name else "(not set)"
|
|
138
143
|
lines.append(("fg:ansibrightblack", f" {name_display}"))
|
|
144
|
+
|
|
145
|
+
# Show name validation hint inline
|
|
146
|
+
name_error = self._validate_server_name(self.server_name)
|
|
147
|
+
if name_error and self.server_name: # Only show if there's input
|
|
148
|
+
lines.append(("", "\n"))
|
|
149
|
+
lines.append(("fg:ansiyellow", f" ⚠ {name_error}"))
|
|
139
150
|
lines.append(("", "\n\n"))
|
|
140
151
|
|
|
141
152
|
# Server Type field
|
|
@@ -201,6 +212,16 @@ class CustomServerForm:
|
|
|
201
212
|
lines.append(("fg:ansired", " Ctrl+C/Esc "))
|
|
202
213
|
lines.append(("", "Cancel"))
|
|
203
214
|
|
|
215
|
+
# Status message bar - shows feedback for user actions
|
|
216
|
+
if self.status_message:
|
|
217
|
+
lines.append(("", "\n\n"))
|
|
218
|
+
lines.append(("bold", " ─" * 20))
|
|
219
|
+
lines.append(("", "\n"))
|
|
220
|
+
if self.status_is_error:
|
|
221
|
+
lines.append(("fg:ansired bold", f" ⚠️ {self.status_message}"))
|
|
222
|
+
else:
|
|
223
|
+
lines.append(("fg:ansigreen bold", f" ✓ {self.status_message}"))
|
|
224
|
+
|
|
204
225
|
return lines
|
|
205
226
|
|
|
206
227
|
def _render_preview(self) -> List:
|
|
@@ -269,6 +290,30 @@ class CustomServerForm:
|
|
|
269
290
|
|
|
270
291
|
return lines
|
|
271
292
|
|
|
293
|
+
def _validate_server_name(self, name: str) -> Optional[str]:
|
|
294
|
+
"""Validate server name format.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
name: Server name to validate
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Error message if invalid, None if valid
|
|
301
|
+
"""
|
|
302
|
+
if not name or not name.strip():
|
|
303
|
+
return "Server name is required"
|
|
304
|
+
|
|
305
|
+
name = name.strip()
|
|
306
|
+
|
|
307
|
+
# Check for valid characters (alphanumeric, hyphens, underscores)
|
|
308
|
+
if not name.replace("-", "").replace("_", "").isalnum():
|
|
309
|
+
return "Name must be alphanumeric (hyphens/underscores OK)"
|
|
310
|
+
|
|
311
|
+
# Check for reasonable length
|
|
312
|
+
if len(name) > 64:
|
|
313
|
+
return "Name too long (max 64 characters)"
|
|
314
|
+
|
|
315
|
+
return None
|
|
316
|
+
|
|
272
317
|
def _validate_json(self) -> bool:
|
|
273
318
|
"""Validate the current JSON configuration.
|
|
274
319
|
|
|
@@ -304,11 +349,17 @@ class CustomServerForm:
|
|
|
304
349
|
from code_puppy.config import MCP_SERVERS_FILE
|
|
305
350
|
from code_puppy.mcp_.managed_server import ServerConfig
|
|
306
351
|
|
|
307
|
-
|
|
308
|
-
|
|
352
|
+
# Validate server name first
|
|
353
|
+
name_error = self._validate_server_name(self.server_name)
|
|
354
|
+
if name_error:
|
|
355
|
+
self.validation_error = name_error
|
|
356
|
+
self.status_message = f"Save failed: {name_error}"
|
|
357
|
+
self.status_is_error = True
|
|
309
358
|
return False
|
|
310
359
|
|
|
311
360
|
if not self._validate_json():
|
|
361
|
+
self.status_message = f"Save failed: {self.validation_error}"
|
|
362
|
+
self.status_is_error = True
|
|
312
363
|
return False
|
|
313
364
|
|
|
314
365
|
server_name = self.server_name.strip()
|
|
@@ -329,6 +380,10 @@ class CustomServerForm:
|
|
|
329
380
|
|
|
330
381
|
if not server_id:
|
|
331
382
|
self.validation_error = "Failed to register server"
|
|
383
|
+
self.status_message = (
|
|
384
|
+
"Save failed: Could not register server (name may already exist)"
|
|
385
|
+
)
|
|
386
|
+
self.status_is_error = True
|
|
332
387
|
return False
|
|
333
388
|
|
|
334
389
|
# Save to mcp_servers.json for persistence
|
|
@@ -363,6 +418,8 @@ class CustomServerForm:
|
|
|
363
418
|
|
|
364
419
|
except Exception as e:
|
|
365
420
|
self.validation_error = f"Error: {e}"
|
|
421
|
+
self.status_message = f"Save failed: {e}"
|
|
422
|
+
self.status_is_error = True
|
|
366
423
|
return False
|
|
367
424
|
|
|
368
425
|
def run(self) -> bool:
|
|
@@ -550,10 +607,14 @@ class CustomServerForm:
|
|
|
550
607
|
# Handle result
|
|
551
608
|
if self.result == "installed":
|
|
552
609
|
if self.edit_mode:
|
|
553
|
-
|
|
610
|
+
emit_success(
|
|
611
|
+
f"\n ✅ Successfully updated server '{self.server_name}'!"
|
|
612
|
+
)
|
|
554
613
|
else:
|
|
555
|
-
|
|
556
|
-
|
|
614
|
+
emit_success(
|
|
615
|
+
f"\n ✅ Successfully added custom server '{self.server_name}'!"
|
|
616
|
+
)
|
|
617
|
+
emit_info(f" Use '/mcp start {self.server_name}' to start the server.\n")
|
|
557
618
|
return True
|
|
558
619
|
|
|
559
620
|
return False
|
|
@@ -7,7 +7,7 @@ custom MCP servers with JSON configuration.
|
|
|
7
7
|
import json
|
|
8
8
|
import os
|
|
9
9
|
|
|
10
|
-
from code_puppy.messaging import emit_error, emit_warning
|
|
10
|
+
from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
|
|
11
11
|
|
|
12
12
|
# Example configurations for each server type
|
|
13
13
|
CUSTOM_SERVER_EXAMPLES = {
|
|
@@ -53,8 +53,8 @@ def prompt_and_install_custom_server(manager) -> bool:
|
|
|
53
53
|
|
|
54
54
|
from .utils import find_server_id_by_name
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
emit_info("\n➕ Add Custom MCP Server\n")
|
|
57
|
+
emit_info(" Configure your own MCP server using JSON.\n")
|
|
58
58
|
|
|
59
59
|
# Get server name
|
|
60
60
|
try:
|
|
@@ -63,7 +63,7 @@ def prompt_and_install_custom_server(manager) -> bool:
|
|
|
63
63
|
emit_warning("Server name is required")
|
|
64
64
|
return False
|
|
65
65
|
except (KeyboardInterrupt, EOFError):
|
|
66
|
-
|
|
66
|
+
emit_info("")
|
|
67
67
|
emit_warning("Cancelled")
|
|
68
68
|
return False
|
|
69
69
|
|
|
@@ -78,20 +78,20 @@ def prompt_and_install_custom_server(manager) -> bool:
|
|
|
78
78
|
emit_warning("Cancelled")
|
|
79
79
|
return False
|
|
80
80
|
except (KeyboardInterrupt, EOFError):
|
|
81
|
-
|
|
81
|
+
emit_info("")
|
|
82
82
|
emit_warning("Cancelled")
|
|
83
83
|
return False
|
|
84
84
|
|
|
85
85
|
# Select server type
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
emit_info("\n Select server type:\n")
|
|
87
|
+
emit_info(" 1. 📟 stdio - Local command (npx, python, uvx, etc.)")
|
|
88
|
+
emit_info(" 2. 🌐 http - HTTP endpoint")
|
|
89
|
+
emit_info(" 3. 📡 sse - Server-Sent Events\n")
|
|
90
90
|
|
|
91
91
|
try:
|
|
92
92
|
type_choice = input(" Enter choice [1-3]: ").strip()
|
|
93
93
|
except (KeyboardInterrupt, EOFError):
|
|
94
|
-
|
|
94
|
+
emit_info("")
|
|
95
95
|
emit_warning("Cancelled")
|
|
96
96
|
return False
|
|
97
97
|
|
|
@@ -103,13 +103,13 @@ def prompt_and_install_custom_server(manager) -> bool:
|
|
|
103
103
|
|
|
104
104
|
# Show example for selected type
|
|
105
105
|
example = CUSTOM_SERVER_EXAMPLES.get(server_type, "{}")
|
|
106
|
-
|
|
106
|
+
emit_info(f"\n Example {server_type} configuration:\n")
|
|
107
107
|
for line in example.split("\n"):
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
emit_info(f" {line}")
|
|
109
|
+
emit_info("")
|
|
110
110
|
|
|
111
111
|
# Get JSON configuration
|
|
112
|
-
|
|
112
|
+
emit_info(" Enter your JSON configuration (paste and press Enter twice):\n")
|
|
113
113
|
|
|
114
114
|
json_lines = []
|
|
115
115
|
empty_count = 0
|
|
@@ -125,7 +125,7 @@ def prompt_and_install_custom_server(manager) -> bool:
|
|
|
125
125
|
empty_count = 0
|
|
126
126
|
json_lines.append(line)
|
|
127
127
|
except (KeyboardInterrupt, EOFError):
|
|
128
|
-
|
|
128
|
+
emit_info("")
|
|
129
129
|
emit_warning("Cancelled")
|
|
130
130
|
return False
|
|
131
131
|
|
|
@@ -187,8 +187,8 @@ def prompt_and_install_custom_server(manager) -> bool:
|
|
|
187
187
|
with open(MCP_SERVERS_FILE, "w") as f:
|
|
188
188
|
json.dump(data, f, indent=2)
|
|
189
189
|
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
emit_success(f"\n ✅ Successfully added custom server '{server_name}'!")
|
|
191
|
+
emit_info(f" Use '/mcp start {server_name}' to start the server.\n")
|
|
192
192
|
return True
|
|
193
193
|
|
|
194
194
|
except Exception as e:
|
|
@@ -8,9 +8,10 @@ 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
|
-
from code_puppy.messaging import emit_info
|
|
13
|
-
from code_puppy.tui_state import is_tui_mode
|
|
14
|
+
from code_puppy.messaging import emit_error, emit_info, emit_warning
|
|
14
15
|
|
|
15
16
|
from .base import MCPCommandBase
|
|
16
17
|
from .custom_server_form import run_custom_server_form
|
|
@@ -37,18 +38,10 @@ class EditCommand(MCPCommandBase):
|
|
|
37
38
|
group_id = self.generate_group_id()
|
|
38
39
|
|
|
39
40
|
try:
|
|
40
|
-
# If in TUI mode, show message
|
|
41
|
-
if is_tui_mode():
|
|
42
|
-
emit_info(
|
|
43
|
-
"In TUI mode, use Ctrl+T to manage MCP servers",
|
|
44
|
-
message_group=group_id,
|
|
45
|
-
)
|
|
46
|
-
return
|
|
47
|
-
|
|
48
41
|
# Need a server name
|
|
49
42
|
if not args:
|
|
50
43
|
emit_info(
|
|
51
|
-
"[yellow]Usage: /mcp edit <server_name>[/yellow]",
|
|
44
|
+
Text.from_markup("[yellow]Usage: /mcp edit <server_name>[/yellow]"),
|
|
52
45
|
message_group=group_id,
|
|
53
46
|
)
|
|
54
47
|
emit_info(
|
|
@@ -86,7 +79,7 @@ class EditCommand(MCPCommandBase):
|
|
|
86
79
|
|
|
87
80
|
except Exception as e:
|
|
88
81
|
logger.error(f"Error editing server: {e}")
|
|
89
|
-
|
|
82
|
+
emit_error(f"Error: {e}", message_group=group_id)
|
|
90
83
|
|
|
91
84
|
def _load_server_config(
|
|
92
85
|
self, server_name: str, group_id: str
|
|
@@ -101,8 +94,8 @@ class EditCommand(MCPCommandBase):
|
|
|
101
94
|
Tuple of (server_type, config_dict) or None if not found
|
|
102
95
|
"""
|
|
103
96
|
if not os.path.exists(MCP_SERVERS_FILE):
|
|
104
|
-
|
|
105
|
-
"
|
|
97
|
+
emit_error(
|
|
98
|
+
"No MCP servers configured yet.",
|
|
106
99
|
message_group=group_id,
|
|
107
100
|
)
|
|
108
101
|
emit_info(
|
|
@@ -118,14 +111,14 @@ class EditCommand(MCPCommandBase):
|
|
|
118
111
|
servers = data.get("mcp_servers", {})
|
|
119
112
|
|
|
120
113
|
if server_name not in servers:
|
|
121
|
-
|
|
122
|
-
f"
|
|
114
|
+
emit_error(
|
|
115
|
+
f"Server '{server_name}' not found.",
|
|
123
116
|
message_group=group_id,
|
|
124
117
|
)
|
|
125
118
|
# Show available servers
|
|
126
119
|
if servers:
|
|
127
|
-
|
|
128
|
-
"\
|
|
120
|
+
emit_warning(
|
|
121
|
+
"\nAvailable servers:",
|
|
129
122
|
message_group=group_id,
|
|
130
123
|
)
|
|
131
124
|
for name in sorted(servers.keys()):
|
|
@@ -142,14 +135,14 @@ class EditCommand(MCPCommandBase):
|
|
|
142
135
|
return (server_type, config)
|
|
143
136
|
|
|
144
137
|
except json.JSONDecodeError as e:
|
|
145
|
-
|
|
146
|
-
f"
|
|
138
|
+
emit_error(
|
|
139
|
+
f"Error reading config file: {e}",
|
|
147
140
|
message_group=group_id,
|
|
148
141
|
)
|
|
149
142
|
return None
|
|
150
143
|
except Exception as e:
|
|
151
|
-
|
|
152
|
-
f"
|
|
144
|
+
emit_error(
|
|
145
|
+
f"Error loading server config: {e}",
|
|
153
146
|
message_group=group_id,
|
|
154
147
|
)
|
|
155
148
|
return None
|
|
@@ -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(
|
|
@@ -7,7 +7,7 @@ from typing import List, Optional
|
|
|
7
7
|
|
|
8
8
|
from rich.text import Text
|
|
9
9
|
|
|
10
|
-
from code_puppy.messaging import emit_info
|
|
10
|
+
from code_puppy.messaging import emit_error, emit_info
|
|
11
11
|
|
|
12
12
|
from .base import MCPCommandBase
|
|
13
13
|
|
|
@@ -148,4 +148,4 @@ class HelpCommand(MCPCommandBase):
|
|
|
148
148
|
|
|
149
149
|
except Exception as e:
|
|
150
150
|
logger.error(f"Error showing help: {e}")
|
|
151
|
-
|
|
151
|
+
emit_error(f"Error showing help: {e}", message_group=group_id)
|
|
@@ -5,8 +5,9 @@ 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
|
|
9
|
-
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
|
|
10
|
+
from code_puppy.messaging import emit_error, emit_info
|
|
10
11
|
|
|
11
12
|
from .base import MCPCommandBase
|
|
12
13
|
from .install_menu import run_mcp_install_menu
|
|
@@ -34,14 +35,6 @@ class InstallCommand(MCPCommandBase):
|
|
|
34
35
|
group_id = self.generate_group_id()
|
|
35
36
|
|
|
36
37
|
try:
|
|
37
|
-
# If in TUI mode, show message to use Ctrl+T
|
|
38
|
-
if is_tui_mode():
|
|
39
|
-
emit_info(
|
|
40
|
-
"In TUI mode, use Ctrl+T to open the MCP Install Wizard",
|
|
41
|
-
message_group=group_id,
|
|
42
|
-
)
|
|
43
|
-
return
|
|
44
|
-
|
|
45
38
|
# In interactive mode, use the menu-based browser
|
|
46
39
|
if not args:
|
|
47
40
|
# No args - launch interactive menu
|
|
@@ -159,7 +152,9 @@ class InstallCommand(MCPCommandBase):
|
|
|
159
152
|
required_env_vars = selected_server.get_environment_vars()
|
|
160
153
|
if required_env_vars:
|
|
161
154
|
emit_info(
|
|
162
|
-
|
|
155
|
+
Text.from_markup(
|
|
156
|
+
"\n[yellow]Required Environment Variables:[/yellow]"
|
|
157
|
+
),
|
|
163
158
|
message_group=group_id,
|
|
164
159
|
)
|
|
165
160
|
for var in required_env_vars:
|
|
@@ -169,7 +164,7 @@ class InstallCommand(MCPCommandBase):
|
|
|
169
164
|
current_value = os.environ.get(var, "")
|
|
170
165
|
if current_value:
|
|
171
166
|
emit_info(
|
|
172
|
-
f" {var}: [green]Already set[/green]",
|
|
167
|
+
Text.from_markup(f" {var}: [green]Already set[/green]"),
|
|
173
168
|
message_group=group_id,
|
|
174
169
|
)
|
|
175
170
|
env_vars[var] = current_value
|
|
@@ -182,7 +177,8 @@ class InstallCommand(MCPCommandBase):
|
|
|
182
177
|
required_cmd_args = selected_server.get_command_line_args()
|
|
183
178
|
if required_cmd_args:
|
|
184
179
|
emit_info(
|
|
185
|
-
"\n[yellow]Command Line Arguments:[/yellow]",
|
|
180
|
+
Text.from_markup("\n[yellow]Command Line Arguments:[/yellow]"),
|
|
181
|
+
message_group=group_id,
|
|
186
182
|
)
|
|
187
183
|
for arg_config in required_cmd_args:
|
|
188
184
|
name = arg_config.get("name", "")
|
|
@@ -214,5 +210,5 @@ class InstallCommand(MCPCommandBase):
|
|
|
214
210
|
return False
|
|
215
211
|
except Exception as e:
|
|
216
212
|
logger.error(f"Error installing from catalog: {e}")
|
|
217
|
-
|
|
213
|
+
emit_error(f"Installation error: {e}", message_group=group_id)
|
|
218
214
|
return False
|
|
@@ -16,7 +16,7 @@ from prompt_toolkit.layout import Dimension, Layout, VSplit, Window
|
|
|
16
16
|
from prompt_toolkit.layout.controls import FormattedTextControl
|
|
17
17
|
from prompt_toolkit.widgets import Frame
|
|
18
18
|
|
|
19
|
-
from code_puppy.messaging import emit_error
|
|
19
|
+
from code_puppy.messaging import emit_error, emit_warning
|
|
20
20
|
from code_puppy.tools.command_runner import set_awaiting_user_input
|
|
21
21
|
|
|
22
22
|
from .catalog_server_installer import (
|
|
@@ -501,11 +501,7 @@ class MCPInstallMenu:
|
|
|
501
501
|
True if a server was installed, False otherwise
|
|
502
502
|
"""
|
|
503
503
|
if not self.categories:
|
|
504
|
-
|
|
505
|
-
try:
|
|
506
|
-
print("No MCP server catalog available.")
|
|
507
|
-
finally:
|
|
508
|
-
set_awaiting_user_input(False)
|
|
504
|
+
emit_warning("No MCP server catalog available.")
|
|
509
505
|
return False
|
|
510
506
|
|
|
511
507
|
# Build UI
|
|
@@ -9,7 +9,7 @@ from rich.table import Table
|
|
|
9
9
|
from rich.text import Text
|
|
10
10
|
|
|
11
11
|
from code_puppy.mcp_.managed_server import ServerState
|
|
12
|
-
from code_puppy.messaging import emit_info
|
|
12
|
+
from code_puppy.messaging import emit_error, emit_info
|
|
13
13
|
|
|
14
14
|
from .base import MCPCommandBase
|
|
15
15
|
from .utils import format_state_indicator, format_uptime
|
|
@@ -91,4 +91,4 @@ class ListCommand(MCPCommandBase):
|
|
|
91
91
|
|
|
92
92
|
except Exception as e:
|
|
93
93
|
logger.error(f"Error listing MCP servers: {e}")
|
|
94
|
-
|
|
94
|
+
emit_error(f"Error listing servers: {e}", message_group=group_id)
|