code-puppy 0.0.302__py3-none-any.whl → 0.0.335__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 +343 -35
- code_puppy/chatgpt_codex_client.py +283 -0
- code_puppy/cli_runner.py +898 -0
- code_puppy/command_line/add_model_menu.py +23 -1
- code_puppy/command_line/autosave_menu.py +271 -35
- code_puppy/command_line/colors_menu.py +520 -0
- code_puppy/command_line/command_handler.py +8 -2
- code_puppy/command_line/config_commands.py +82 -10
- code_puppy/command_line/core_commands.py +70 -7
- code_puppy/command_line/diff_menu.py +5 -0
- code_puppy/command_line/mcp/custom_server_form.py +4 -0
- 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/install_menu.py +5 -1
- 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 +58 -7
- code_puppy/command_line/motd.py +13 -7
- code_puppy/command_line/onboarding_slides.py +180 -0
- code_puppy/command_line/onboarding_wizard.py +340 -0
- code_puppy/command_line/prompt_toolkit_completion.py +16 -2
- code_puppy/command_line/session_commands.py +11 -4
- code_puppy/config.py +106 -17
- code_puppy/http_utils.py +155 -196
- code_puppy/keymap.py +8 -0
- 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 +271 -45
- code_puppy/model_utils.py +57 -48
- code_puppy/models.json +21 -7
- code_puppy/plugins/__init__.py +12 -0
- code_puppy/plugins/antigravity_oauth/__init__.py +10 -0
- code_puppy/plugins/antigravity_oauth/accounts.py +406 -0
- code_puppy/plugins/antigravity_oauth/antigravity_model.py +612 -0
- code_puppy/plugins/antigravity_oauth/config.py +42 -0
- code_puppy/plugins/antigravity_oauth/constants.py +136 -0
- code_puppy/plugins/antigravity_oauth/oauth.py +478 -0
- code_puppy/plugins/antigravity_oauth/register_callbacks.py +406 -0
- code_puppy/plugins/antigravity_oauth/storage.py +271 -0
- code_puppy/plugins/antigravity_oauth/test_plugin.py +319 -0
- code_puppy/plugins/antigravity_oauth/token.py +167 -0
- code_puppy/plugins/antigravity_oauth/transport.py +595 -0
- code_puppy/plugins/antigravity_oauth/utils.py +169 -0
- 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 +5 -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 +30 -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/reopenable_async_client.py +8 -8
- code_puppy/terminal_utils.py +291 -0
- code_puppy/tools/agent_tools.py +34 -9
- code_puppy/tools/command_runner.py +344 -27
- code_puppy/tools/file_operations.py +33 -45
- code_puppy/uvx_detection.py +242 -0
- {code_puppy-0.0.302.data → code_puppy-0.0.335.data}/data/code_puppy/models.json +21 -7
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.335.dist-info}/METADATA +30 -1
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.335.dist-info}/RECORD +87 -64
- {code_puppy-0.0.302.data → code_puppy-0.0.335.data}/data/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.335.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.335.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.302.dist-info → code_puppy-0.0.335.dist-info}/licenses/LICENSE +0 -0
|
@@ -27,6 +27,8 @@ def get_commands_help():
|
|
|
27
27
|
)
|
|
28
28
|
def handle_show_command(command: str) -> bool:
|
|
29
29
|
"""Show current puppy configuration."""
|
|
30
|
+
from rich.text import Text
|
|
31
|
+
|
|
30
32
|
from code_puppy.agents import get_current_agent
|
|
31
33
|
from code_puppy.command_line.model_picker_completion import get_active_model
|
|
32
34
|
from code_puppy.config import (
|
|
@@ -44,6 +46,7 @@ def handle_show_command(command: str) -> bool:
|
|
|
44
46
|
get_use_dbos,
|
|
45
47
|
get_yolo_mode,
|
|
46
48
|
)
|
|
49
|
+
from code_puppy.keymap import get_cancel_agent_display_name
|
|
47
50
|
from code_puppy.messaging import emit_info
|
|
48
51
|
|
|
49
52
|
puppy_name = get_puppy_name()
|
|
@@ -77,16 +80,17 @@ def handle_show_command(command: str) -> bool:
|
|
|
77
80
|
[bold]reasoning_effort:[/bold] [cyan]{get_openai_reasoning_effort()}[/cyan]
|
|
78
81
|
[bold]verbosity:[/bold] [cyan]{get_openai_verbosity()}[/cyan]
|
|
79
82
|
[bold]temperature:[/bold] [cyan]{effective_temperature if effective_temperature is not None else "(model default)"}[/cyan]{" (per-model)" if effective_temperature != global_temperature and effective_temperature is not None else ""}
|
|
83
|
+
[bold]cancel_agent_key:[/bold] [cyan]{get_cancel_agent_display_name()}[/cyan] (options: ctrl+c, ctrl+k, ctrl+q)
|
|
80
84
|
|
|
81
85
|
"""
|
|
82
|
-
emit_info(status_msg)
|
|
86
|
+
emit_info(Text.from_markup(status_msg))
|
|
83
87
|
return True
|
|
84
88
|
|
|
85
89
|
|
|
86
90
|
@register_command(
|
|
87
91
|
name="reasoning",
|
|
88
92
|
description="Set OpenAI reasoning effort for GPT-5 models (e.g., /reasoning high)",
|
|
89
|
-
usage="/reasoning <low|medium|high>",
|
|
93
|
+
usage="/reasoning <minimal|low|medium|high|xhigh>",
|
|
90
94
|
category="config",
|
|
91
95
|
)
|
|
92
96
|
def handle_reasoning_command(command: str) -> bool:
|
|
@@ -95,7 +99,7 @@ def handle_reasoning_command(command: str) -> bool:
|
|
|
95
99
|
|
|
96
100
|
tokens = command.split()
|
|
97
101
|
if len(tokens) != 2:
|
|
98
|
-
emit_warning("Usage: /reasoning <low|medium|high>")
|
|
102
|
+
emit_warning("Usage: /reasoning <minimal|low|medium|high|xhigh>")
|
|
99
103
|
return True
|
|
100
104
|
|
|
101
105
|
effort = tokens[1]
|
|
@@ -171,6 +175,8 @@ def handle_verbosity_command(command: str) -> bool:
|
|
|
171
175
|
)
|
|
172
176
|
def handle_set_command(command: str) -> bool:
|
|
173
177
|
"""Set configuration values."""
|
|
178
|
+
from rich.text import Text
|
|
179
|
+
|
|
174
180
|
from code_puppy.config import set_config_value
|
|
175
181
|
from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
|
|
176
182
|
|
|
@@ -196,15 +202,40 @@ def handle_set_command(command: str) -> bool:
|
|
|
196
202
|
"\n[yellow]Session Management[/yellow]"
|
|
197
203
|
"\n [cyan]auto_save_session[/cyan] Auto-save chat after every response (true/false)"
|
|
198
204
|
)
|
|
205
|
+
keymap_help = (
|
|
206
|
+
"\n[yellow]Keyboard Shortcuts[/yellow]"
|
|
207
|
+
"\n [cyan]cancel_agent_key[/cyan] Key to cancel agent tasks (ctrl+c, ctrl+k, or ctrl+q)"
|
|
208
|
+
)
|
|
199
209
|
emit_warning(
|
|
200
|
-
|
|
210
|
+
Text.from_markup(
|
|
211
|
+
f"Usage: /set KEY=VALUE or /set KEY VALUE\nConfig keys: {', '.join(config_keys)}\n[dim]Note: compaction_strategy can be 'summarization' or 'truncation'[/dim]{session_help}{keymap_help}"
|
|
212
|
+
)
|
|
201
213
|
)
|
|
202
214
|
return True
|
|
203
215
|
if key:
|
|
204
216
|
# Check if we're toggling DBOS enablement
|
|
205
217
|
if key == "enable_dbos":
|
|
206
218
|
emit_info(
|
|
207
|
-
|
|
219
|
+
Text.from_markup(
|
|
220
|
+
"[yellow]⚠️ DBOS configuration changed. Please restart Code Puppy for this change to take effect.[/yellow]"
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# Validate cancel_agent_key before setting
|
|
225
|
+
if key == "cancel_agent_key":
|
|
226
|
+
from code_puppy.keymap import VALID_CANCEL_KEYS
|
|
227
|
+
|
|
228
|
+
normalized_value = value.strip().lower()
|
|
229
|
+
if normalized_value not in VALID_CANCEL_KEYS:
|
|
230
|
+
emit_error(
|
|
231
|
+
f"Invalid cancel_agent_key '{value}'. Valid options: {', '.join(sorted(VALID_CANCEL_KEYS))}"
|
|
232
|
+
)
|
|
233
|
+
return True
|
|
234
|
+
value = normalized_value # Use normalized value
|
|
235
|
+
emit_info(
|
|
236
|
+
Text.from_markup(
|
|
237
|
+
"[yellow]⚠️ cancel_agent_key changed. Please restart Code Puppy for this change to take effect.[/yellow]"
|
|
238
|
+
)
|
|
208
239
|
)
|
|
209
240
|
|
|
210
241
|
set_config_value(key, value)
|
|
@@ -539,6 +570,37 @@ def handle_diff_command(command: str) -> bool:
|
|
|
539
570
|
return True
|
|
540
571
|
|
|
541
572
|
|
|
573
|
+
@register_command(
|
|
574
|
+
name="colors",
|
|
575
|
+
description="Configure banner colors for tool outputs (THINKING, SHELL COMMAND, etc.)",
|
|
576
|
+
usage="/colors",
|
|
577
|
+
category="config",
|
|
578
|
+
)
|
|
579
|
+
def handle_colors_command(command: str) -> bool:
|
|
580
|
+
"""Configure banner colors via interactive TUI."""
|
|
581
|
+
import asyncio
|
|
582
|
+
import concurrent.futures
|
|
583
|
+
|
|
584
|
+
from code_puppy.command_line.colors_menu import interactive_colors_picker
|
|
585
|
+
from code_puppy.config import set_banner_color
|
|
586
|
+
from code_puppy.messaging import emit_error, emit_success
|
|
587
|
+
|
|
588
|
+
# Show interactive picker for banner color configuration
|
|
589
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
590
|
+
future = executor.submit(lambda: asyncio.run(interactive_colors_picker()))
|
|
591
|
+
result = future.result(timeout=300) # 5 min timeout
|
|
592
|
+
|
|
593
|
+
if result:
|
|
594
|
+
# Apply the changes
|
|
595
|
+
try:
|
|
596
|
+
for banner_name, color in result.items():
|
|
597
|
+
set_banner_color(banner_name, color)
|
|
598
|
+
emit_success("Banner colors saved! 🎨")
|
|
599
|
+
except Exception as e:
|
|
600
|
+
emit_error(f"Failed to apply banner color settings: {e}")
|
|
601
|
+
return True
|
|
602
|
+
|
|
603
|
+
|
|
542
604
|
# ============================================================================
|
|
543
605
|
# UTILITY FUNCTIONS
|
|
544
606
|
# ============================================================================
|
|
@@ -550,6 +612,8 @@ def _show_color_options(color_type: str):
|
|
|
550
612
|
# ============================================================================
|
|
551
613
|
|
|
552
614
|
"""Show available Rich color options organized by category."""
|
|
615
|
+
from rich.text import Text
|
|
616
|
+
|
|
553
617
|
from code_puppy.messaging import emit_info
|
|
554
618
|
|
|
555
619
|
# Standard Rich colors organized by category
|
|
@@ -607,11 +671,15 @@ def _show_color_options(color_type: str):
|
|
|
607
671
|
("sea_green1", "🟢"),
|
|
608
672
|
]
|
|
609
673
|
emit_info(
|
|
610
|
-
|
|
674
|
+
Text.from_markup(
|
|
675
|
+
"[bold white on green]🎨 Recommended Colors for Additions:[/bold white on green]"
|
|
676
|
+
)
|
|
611
677
|
)
|
|
612
678
|
for color, emoji in suggestions:
|
|
613
679
|
emit_info(
|
|
614
|
-
|
|
680
|
+
Text.from_markup(
|
|
681
|
+
f" [cyan]{color:<16}[/cyan] [white on {color}]■■■■■■■■■■[/white on {color}] {emoji}"
|
|
682
|
+
)
|
|
615
683
|
)
|
|
616
684
|
elif color_type == "deletions":
|
|
617
685
|
suggestions = [
|
|
@@ -622,11 +690,15 @@ def _show_color_options(color_type: str):
|
|
|
622
690
|
("dark_red", "🔴"),
|
|
623
691
|
]
|
|
624
692
|
emit_info(
|
|
625
|
-
|
|
693
|
+
Text.from_markup(
|
|
694
|
+
"[bold white on orange1]🎨 Recommended Colors for Deletions:[/bold white on orange1]"
|
|
695
|
+
)
|
|
626
696
|
)
|
|
627
697
|
for color, emoji in suggestions:
|
|
628
698
|
emit_info(
|
|
629
|
-
|
|
699
|
+
Text.from_markup(
|
|
700
|
+
f" [cyan]{color:<16}[/cyan] [white on {color}]■■■■■■■■■■[/white on {color}] {emoji}"
|
|
701
|
+
)
|
|
630
702
|
)
|
|
631
703
|
|
|
632
704
|
emit_info("\n🎨 All Available Rich Colors:")
|
|
@@ -636,7 +708,7 @@ def _show_color_options(color_type: str):
|
|
|
636
708
|
for i in range(0, len(colors), 4):
|
|
637
709
|
row = colors[i : i + 4]
|
|
638
710
|
row_text = " ".join([f"[{color}]■[/{color}] {color}" for color, _ in row])
|
|
639
|
-
emit_info(f" {row_text}")
|
|
711
|
+
emit_info(Text.from_markup(f" {row_text}"))
|
|
640
712
|
|
|
641
713
|
emit_info("\nUsage: /diff {color_type} <color_name>")
|
|
642
714
|
emit_info("All diffs use white text on your chosen background colors")
|
|
@@ -115,6 +115,57 @@ def handle_motd_command(command: str) -> bool:
|
|
|
115
115
|
return True
|
|
116
116
|
|
|
117
117
|
|
|
118
|
+
@register_command(
|
|
119
|
+
name="tutorial",
|
|
120
|
+
description="Run the interactive tutorial wizard",
|
|
121
|
+
usage="/tutorial",
|
|
122
|
+
category="core",
|
|
123
|
+
)
|
|
124
|
+
def handle_tutorial_command(command: str) -> bool:
|
|
125
|
+
"""Run the interactive tutorial wizard.
|
|
126
|
+
|
|
127
|
+
Usage:
|
|
128
|
+
/tutorial - Run the tutorial (can be run anytime)
|
|
129
|
+
"""
|
|
130
|
+
import asyncio
|
|
131
|
+
import concurrent.futures
|
|
132
|
+
|
|
133
|
+
from code_puppy.command_line.onboarding_wizard import (
|
|
134
|
+
reset_onboarding,
|
|
135
|
+
run_onboarding_wizard,
|
|
136
|
+
)
|
|
137
|
+
from code_puppy.config import set_model_name
|
|
138
|
+
|
|
139
|
+
# Always reset so user can re-run the tutorial anytime
|
|
140
|
+
reset_onboarding()
|
|
141
|
+
|
|
142
|
+
# Run the async wizard in a thread pool (same pattern as agent picker)
|
|
143
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
144
|
+
future = executor.submit(lambda: asyncio.run(run_onboarding_wizard()))
|
|
145
|
+
result = future.result(timeout=300) # 5 min timeout
|
|
146
|
+
|
|
147
|
+
if result == "chatgpt":
|
|
148
|
+
emit_info("🔐 Starting ChatGPT OAuth flow...")
|
|
149
|
+
from code_puppy.plugins.chatgpt_oauth.oauth_flow import run_oauth_flow
|
|
150
|
+
|
|
151
|
+
run_oauth_flow()
|
|
152
|
+
set_model_name("chatgpt-gpt-5.2-codex")
|
|
153
|
+
elif result == "claude":
|
|
154
|
+
emit_info("🔐 Starting Claude Code OAuth flow...")
|
|
155
|
+
from code_puppy.plugins.claude_code_oauth.register_callbacks import (
|
|
156
|
+
_perform_authentication,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
_perform_authentication()
|
|
160
|
+
set_model_name("claude-code-claude-opus-4-5-20251101")
|
|
161
|
+
elif result == "completed":
|
|
162
|
+
emit_info("🎉 Tutorial complete! Happy coding!")
|
|
163
|
+
elif result == "skipped":
|
|
164
|
+
emit_info("⏭️ Tutorial skipped. Run /tutorial anytime!")
|
|
165
|
+
|
|
166
|
+
return True
|
|
167
|
+
|
|
168
|
+
|
|
118
169
|
@register_command(
|
|
119
170
|
name="exit",
|
|
120
171
|
description="Exit interactive mode",
|
|
@@ -145,6 +196,8 @@ def handle_exit_command(command: str) -> bool:
|
|
|
145
196
|
)
|
|
146
197
|
def handle_agent_command(command: str) -> bool:
|
|
147
198
|
"""Handle agent switching."""
|
|
199
|
+
from rich.text import Text
|
|
200
|
+
|
|
148
201
|
from code_puppy.agents import (
|
|
149
202
|
get_agent_descriptions,
|
|
150
203
|
get_available_agents,
|
|
@@ -201,7 +254,9 @@ def handle_agent_command(command: str) -> bool:
|
|
|
201
254
|
)
|
|
202
255
|
emit_info(f"{new_agent.description}", message_group=group_id)
|
|
203
256
|
emit_info(
|
|
204
|
-
|
|
257
|
+
Text.from_markup(
|
|
258
|
+
f"[dim]Auto-save session rotated to: {new_session_id}[/dim]"
|
|
259
|
+
),
|
|
205
260
|
message_group=group_id,
|
|
206
261
|
)
|
|
207
262
|
else:
|
|
@@ -224,15 +279,19 @@ def handle_agent_command(command: str) -> bool:
|
|
|
224
279
|
group_id = str(uuid.uuid4())
|
|
225
280
|
|
|
226
281
|
emit_info(
|
|
227
|
-
|
|
282
|
+
Text.from_markup(
|
|
283
|
+
f"[bold green]Current Agent:[/bold green] {current_agent.display_name}"
|
|
284
|
+
),
|
|
228
285
|
message_group=group_id,
|
|
229
286
|
)
|
|
230
287
|
emit_info(
|
|
231
|
-
f"[dim]{current_agent.description}[/dim]\n",
|
|
288
|
+
Text.from_markup(f"[dim]{current_agent.description}[/dim]\n"),
|
|
289
|
+
message_group=group_id,
|
|
232
290
|
)
|
|
233
291
|
|
|
234
292
|
emit_info(
|
|
235
|
-
"[bold magenta]Available Agents:[/bold magenta]",
|
|
293
|
+
Text.from_markup("[bold magenta]Available Agents:[/bold magenta]"),
|
|
294
|
+
message_group=group_id,
|
|
236
295
|
)
|
|
237
296
|
for name, display_name in available_agents.items():
|
|
238
297
|
description = descriptions.get(name, "No description")
|
|
@@ -240,13 +299,15 @@ def handle_agent_command(command: str) -> bool:
|
|
|
240
299
|
" [green]← current[/green]" if name == current_agent.name else ""
|
|
241
300
|
)
|
|
242
301
|
emit_info(
|
|
243
|
-
|
|
302
|
+
Text.from_markup(
|
|
303
|
+
f" [cyan]{name:<12}[/cyan] {display_name}{current_marker}"
|
|
304
|
+
),
|
|
244
305
|
message_group=group_id,
|
|
245
306
|
)
|
|
246
307
|
emit_info(f" {description}", message_group=group_id)
|
|
247
308
|
|
|
248
309
|
emit_info(
|
|
249
|
-
"\n[yellow]Usage:[/yellow] /agent <agent-name>",
|
|
310
|
+
Text.from_markup("\n[yellow]Usage:[/yellow] /agent <agent-name>"),
|
|
250
311
|
message_group=group_id,
|
|
251
312
|
)
|
|
252
313
|
return True
|
|
@@ -292,7 +353,9 @@ def handle_agent_command(command: str) -> bool:
|
|
|
292
353
|
)
|
|
293
354
|
emit_info(f"{new_agent.description}", message_group=group_id)
|
|
294
355
|
emit_info(
|
|
295
|
-
|
|
356
|
+
Text.from_markup(
|
|
357
|
+
f"[dim]Auto-save session rotated to: {new_session_id}[/dim]"
|
|
358
|
+
),
|
|
296
359
|
message_group=group_id,
|
|
297
360
|
)
|
|
298
361
|
return True
|
|
@@ -456,6 +456,11 @@ async def interactive_diff_picker() -> Optional[dict]:
|
|
|
456
456
|
sys.stdout.write("\033[?1049l") # Exit alternate buffer
|
|
457
457
|
sys.stdout.flush()
|
|
458
458
|
|
|
459
|
+
# Clear exit message
|
|
460
|
+
from code_puppy.messaging import emit_info
|
|
461
|
+
|
|
462
|
+
emit_info("✓ Exited diff color configuration")
|
|
463
|
+
|
|
459
464
|
# Return changes if any
|
|
460
465
|
if config.has_changes():
|
|
461
466
|
return {
|
|
@@ -604,6 +604,10 @@ class CustomServerForm:
|
|
|
604
604
|
sys.stdout.flush()
|
|
605
605
|
set_awaiting_user_input(False)
|
|
606
606
|
|
|
607
|
+
# Clear exit message if not installing
|
|
608
|
+
if self.result != "installed":
|
|
609
|
+
emit_info("✓ Exited custom server form")
|
|
610
|
+
|
|
607
611
|
# Handle result
|
|
608
612
|
if self.result == "installed":
|
|
609
613
|
if self.edit_mode:
|
|
@@ -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", "")
|
|
@@ -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, emit_warning
|
|
19
|
+
from code_puppy.messaging import emit_error, emit_info, emit_warning
|
|
20
20
|
from code_puppy.tools.command_runner import set_awaiting_user_input
|
|
21
21
|
|
|
22
22
|
from .catalog_server_installer import (
|
|
@@ -635,6 +635,10 @@ class MCPInstallMenu:
|
|
|
635
635
|
sys.stdout.flush()
|
|
636
636
|
set_awaiting_user_input(False)
|
|
637
637
|
|
|
638
|
+
# Clear exit message (unless we're about to prompt for more input)
|
|
639
|
+
if self.result not in ("pending_custom", "pending_install"):
|
|
640
|
+
emit_info("✓ Exited MCP server browser")
|
|
641
|
+
|
|
638
642
|
# Handle custom server after TUI exits
|
|
639
643
|
if self.result == "pending_custom":
|
|
640
644
|
success = run_custom_server_form(self.manager)
|