code-puppy 0.0.214__py3-none-any.whl → 0.0.366__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 +7 -1
- code_puppy/agents/__init__.py +2 -0
- code_puppy/agents/agent_c_reviewer.py +59 -6
- code_puppy/agents/agent_code_puppy.py +7 -1
- code_puppy/agents/agent_code_reviewer.py +12 -2
- code_puppy/agents/agent_cpp_reviewer.py +73 -6
- code_puppy/agents/agent_creator_agent.py +45 -4
- code_puppy/agents/agent_golang_reviewer.py +92 -3
- code_puppy/agents/agent_javascript_reviewer.py +101 -8
- code_puppy/agents/agent_manager.py +81 -4
- code_puppy/agents/agent_pack_leader.py +383 -0
- code_puppy/agents/agent_planning.py +163 -0
- code_puppy/agents/agent_python_programmer.py +165 -0
- code_puppy/agents/agent_python_reviewer.py +28 -6
- code_puppy/agents/agent_qa_expert.py +98 -6
- code_puppy/agents/agent_qa_kitten.py +12 -7
- code_puppy/agents/agent_security_auditor.py +113 -3
- code_puppy/agents/agent_terminal_qa.py +323 -0
- code_puppy/agents/agent_typescript_reviewer.py +106 -7
- code_puppy/agents/base_agent.py +802 -176
- code_puppy/agents/event_stream_handler.py +350 -0
- code_puppy/agents/pack/__init__.py +34 -0
- code_puppy/agents/pack/bloodhound.py +304 -0
- code_puppy/agents/pack/husky.py +321 -0
- code_puppy/agents/pack/retriever.py +393 -0
- code_puppy/agents/pack/shepherd.py +348 -0
- code_puppy/agents/pack/terrier.py +287 -0
- code_puppy/agents/pack/watchdog.py +367 -0
- code_puppy/agents/prompt_reviewer.py +145 -0
- code_puppy/agents/subagent_stream_handler.py +276 -0
- code_puppy/api/__init__.py +13 -0
- code_puppy/api/app.py +169 -0
- code_puppy/api/main.py +21 -0
- code_puppy/api/pty_manager.py +446 -0
- code_puppy/api/routers/__init__.py +12 -0
- code_puppy/api/routers/agents.py +36 -0
- code_puppy/api/routers/commands.py +217 -0
- code_puppy/api/routers/config.py +74 -0
- code_puppy/api/routers/sessions.py +232 -0
- code_puppy/api/templates/terminal.html +361 -0
- code_puppy/api/websocket.py +154 -0
- code_puppy/callbacks.py +142 -4
- code_puppy/chatgpt_codex_client.py +283 -0
- code_puppy/claude_cache_client.py +586 -0
- code_puppy/cli_runner.py +916 -0
- code_puppy/command_line/add_model_menu.py +1079 -0
- code_puppy/command_line/agent_menu.py +395 -0
- code_puppy/command_line/attachments.py +10 -5
- code_puppy/command_line/autosave_menu.py +605 -0
- code_puppy/command_line/clipboard.py +527 -0
- code_puppy/command_line/colors_menu.py +520 -0
- code_puppy/command_line/command_handler.py +176 -738
- code_puppy/command_line/command_registry.py +150 -0
- code_puppy/command_line/config_commands.py +715 -0
- code_puppy/command_line/core_commands.py +792 -0
- code_puppy/command_line/diff_menu.py +863 -0
- code_puppy/command_line/load_context_completion.py +15 -22
- code_puppy/command_line/mcp/base.py +0 -3
- code_puppy/command_line/mcp/catalog_server_installer.py +175 -0
- code_puppy/command_line/mcp/custom_server_form.py +688 -0
- code_puppy/command_line/mcp/custom_server_installer.py +195 -0
- code_puppy/command_line/mcp/edit_command.py +148 -0
- code_puppy/command_line/mcp/handler.py +9 -4
- code_puppy/command_line/mcp/help_command.py +6 -5
- code_puppy/command_line/mcp/install_command.py +15 -26
- code_puppy/command_line/mcp/install_menu.py +685 -0
- 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 +12 -4
- code_puppy/command_line/mcp/search_command.py +16 -10
- code_puppy/command_line/mcp/start_all_command.py +18 -6
- code_puppy/command_line/mcp/start_command.py +47 -25
- code_puppy/command_line/mcp/status_command.py +4 -5
- code_puppy/command_line/mcp/stop_all_command.py +7 -1
- code_puppy/command_line/mcp/stop_command.py +8 -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/mcp_completion.py +174 -0
- code_puppy/command_line/model_picker_completion.py +75 -25
- code_puppy/command_line/model_settings_menu.py +884 -0
- code_puppy/command_line/motd.py +14 -8
- code_puppy/command_line/onboarding_slides.py +179 -0
- code_puppy/command_line/onboarding_wizard.py +340 -0
- code_puppy/command_line/pin_command_completion.py +329 -0
- code_puppy/command_line/prompt_toolkit_completion.py +463 -63
- code_puppy/command_line/session_commands.py +296 -0
- code_puppy/command_line/utils.py +54 -0
- code_puppy/config.py +898 -112
- code_puppy/error_logging.py +118 -0
- code_puppy/gemini_code_assist.py +385 -0
- code_puppy/gemini_model.py +602 -0
- code_puppy/http_utils.py +210 -148
- code_puppy/keymap.py +128 -0
- code_puppy/main.py +5 -698
- code_puppy/mcp_/__init__.py +17 -0
- code_puppy/mcp_/async_lifecycle.py +35 -4
- code_puppy/mcp_/blocking_startup.py +70 -43
- code_puppy/mcp_/captured_stdio_server.py +2 -2
- code_puppy/mcp_/config_wizard.py +4 -4
- code_puppy/mcp_/dashboard.py +15 -6
- code_puppy/mcp_/managed_server.py +65 -38
- code_puppy/mcp_/manager.py +146 -52
- code_puppy/mcp_/mcp_logs.py +224 -0
- code_puppy/mcp_/registry.py +6 -6
- code_puppy/mcp_/server_registry_catalog.py +24 -5
- code_puppy/messaging/__init__.py +199 -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 +17 -48
- code_puppy/messaging/messages.py +500 -0
- code_puppy/messaging/queue_console.py +1 -24
- code_puppy/messaging/renderers.py +43 -146
- code_puppy/messaging/rich_renderer.py +1027 -0
- code_puppy/messaging/spinner/__init__.py +21 -5
- code_puppy/messaging/spinner/console_spinner.py +86 -51
- code_puppy/messaging/subagent_console.py +461 -0
- code_puppy/model_factory.py +634 -83
- code_puppy/model_utils.py +167 -0
- code_puppy/models.json +66 -68
- code_puppy/models_dev_api.json +1 -0
- code_puppy/models_dev_parser.py +592 -0
- code_puppy/plugins/__init__.py +164 -10
- 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 +704 -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 +767 -0
- code_puppy/plugins/antigravity_oauth/utils.py +169 -0
- code_puppy/plugins/chatgpt_oauth/__init__.py +8 -0
- code_puppy/plugins/chatgpt_oauth/config.py +52 -0
- code_puppy/plugins/chatgpt_oauth/oauth_flow.py +328 -0
- code_puppy/plugins/chatgpt_oauth/register_callbacks.py +94 -0
- code_puppy/plugins/chatgpt_oauth/test_plugin.py +293 -0
- code_puppy/plugins/chatgpt_oauth/utils.py +489 -0
- code_puppy/plugins/claude_code_oauth/README.md +167 -0
- code_puppy/plugins/claude_code_oauth/SETUP.md +93 -0
- code_puppy/plugins/claude_code_oauth/__init__.py +6 -0
- code_puppy/plugins/claude_code_oauth/config.py +50 -0
- code_puppy/plugins/claude_code_oauth/register_callbacks.py +308 -0
- code_puppy/plugins/claude_code_oauth/test_plugin.py +283 -0
- code_puppy/plugins/claude_code_oauth/utils.py +518 -0
- code_puppy/plugins/customizable_commands/__init__.py +0 -0
- code_puppy/plugins/customizable_commands/register_callbacks.py +169 -0
- code_puppy/plugins/example_custom_command/README.md +280 -0
- code_puppy/plugins/example_custom_command/register_callbacks.py +2 -2
- code_puppy/plugins/file_permission_handler/__init__.py +4 -0
- code_puppy/plugins/file_permission_handler/register_callbacks.py +523 -0
- code_puppy/plugins/frontend_emitter/__init__.py +25 -0
- code_puppy/plugins/frontend_emitter/emitter.py +121 -0
- code_puppy/plugins/frontend_emitter/register_callbacks.py +261 -0
- code_puppy/plugins/oauth_puppy_html.py +228 -0
- code_puppy/plugins/shell_safety/__init__.py +6 -0
- code_puppy/plugins/shell_safety/agent_shell_safety.py +69 -0
- code_puppy/plugins/shell_safety/command_cache.py +156 -0
- code_puppy/plugins/shell_safety/register_callbacks.py +202 -0
- code_puppy/prompts/antigravity_system_prompt.md +1 -0
- 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/round_robin_model.py +9 -12
- code_puppy/session_storage.py +2 -1
- code_puppy/status_display.py +21 -4
- code_puppy/summarization_agent.py +41 -13
- code_puppy/terminal_utils.py +418 -0
- code_puppy/tools/__init__.py +37 -1
- code_puppy/tools/agent_tools.py +536 -52
- code_puppy/tools/browser/__init__.py +37 -0
- code_puppy/tools/browser/browser_control.py +19 -23
- code_puppy/tools/browser/browser_interactions.py +41 -48
- code_puppy/tools/browser/browser_locators.py +36 -38
- code_puppy/tools/browser/browser_manager.py +316 -0
- code_puppy/tools/browser/browser_navigation.py +16 -16
- code_puppy/tools/browser/browser_screenshot.py +79 -143
- code_puppy/tools/browser/browser_scripts.py +32 -42
- code_puppy/tools/browser/browser_workflows.py +44 -27
- code_puppy/tools/browser/chromium_terminal_manager.py +259 -0
- code_puppy/tools/browser/terminal_command_tools.py +521 -0
- code_puppy/tools/browser/terminal_screenshot_tools.py +556 -0
- code_puppy/tools/browser/terminal_tools.py +525 -0
- code_puppy/tools/command_runner.py +930 -147
- code_puppy/tools/common.py +1113 -5
- code_puppy/tools/display.py +84 -0
- code_puppy/tools/file_modifications.py +288 -89
- code_puppy/tools/file_operations.py +226 -154
- code_puppy/tools/subagent_context.py +158 -0
- code_puppy/uvx_detection.py +242 -0
- code_puppy/version_checker.py +30 -11
- code_puppy-0.0.366.data/data/code_puppy/models.json +110 -0
- code_puppy-0.0.366.data/data/code_puppy/models_dev_api.json +1 -0
- {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/METADATA +149 -75
- code_puppy-0.0.366.dist-info/RECORD +217 -0
- {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/WHEEL +1 -1
- code_puppy/command_line/mcp/add_command.py +0 -183
- code_puppy/messaging/spinner/textual_spinner.py +0 -106
- code_puppy/tools/browser/camoufox_manager.py +0 -216
- code_puppy/tools/browser/vqa_agent.py +0 -70
- code_puppy/tui/__init__.py +0 -10
- code_puppy/tui/app.py +0 -1105
- code_puppy/tui/components/__init__.py +0 -21
- code_puppy/tui/components/chat_view.py +0 -551
- code_puppy/tui/components/command_history_modal.py +0 -218
- code_puppy/tui/components/copy_button.py +0 -139
- code_puppy/tui/components/custom_widgets.py +0 -63
- code_puppy/tui/components/human_input_modal.py +0 -175
- code_puppy/tui/components/input_area.py +0 -167
- code_puppy/tui/components/sidebar.py +0 -309
- code_puppy/tui/components/status_bar.py +0 -185
- code_puppy/tui/messages.py +0 -27
- code_puppy/tui/models/__init__.py +0 -8
- code_puppy/tui/models/chat_message.py +0 -25
- code_puppy/tui/models/command_history.py +0 -89
- code_puppy/tui/models/enums.py +0 -24
- code_puppy/tui/screens/__init__.py +0 -17
- code_puppy/tui/screens/autosave_picker.py +0 -175
- code_puppy/tui/screens/help.py +0 -130
- code_puppy/tui/screens/mcp_install_wizard.py +0 -803
- code_puppy/tui/screens/settings.py +0 -306
- code_puppy/tui/screens/tools.py +0 -74
- code_puppy/tui_state.py +0 -55
- code_puppy-0.0.214.data/data/code_puppy/models.json +0 -112
- code_puppy-0.0.214.dist-info/RECORD +0 -131
- {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/licenses/LICENSE +0 -0
code_puppy/main.py
CHANGED
|
@@ -1,703 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
import asyncio
|
|
3
|
-
import os
|
|
4
|
-
import subprocess
|
|
5
|
-
import sys
|
|
6
|
-
import time
|
|
7
|
-
import webbrowser
|
|
8
|
-
from pathlib import Path
|
|
1
|
+
"""Main entry point for Code Puppy CLI.
|
|
9
2
|
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
from rich.syntax import Syntax
|
|
14
|
-
from rich.text import Text
|
|
15
|
-
|
|
16
|
-
from code_puppy import __version__, callbacks, plugins
|
|
17
|
-
from code_puppy.agents import get_current_agent
|
|
18
|
-
from code_puppy.command_line.prompt_toolkit_completion import (
|
|
19
|
-
get_input_with_combined_completion,
|
|
20
|
-
get_prompt_with_active_model,
|
|
21
|
-
)
|
|
22
|
-
from code_puppy.command_line.attachments import parse_prompt_attachments
|
|
23
|
-
from code_puppy.config import (
|
|
24
|
-
AUTOSAVE_DIR,
|
|
25
|
-
COMMAND_HISTORY_FILE,
|
|
26
|
-
DBOS_DATABASE_URL,
|
|
27
|
-
get_use_dbos,
|
|
28
|
-
ensure_config_exists,
|
|
29
|
-
finalize_autosave_session,
|
|
30
|
-
initialize_command_history_file,
|
|
31
|
-
save_command_to_history,
|
|
32
|
-
)
|
|
33
|
-
from code_puppy.session_storage import restore_autosave_interactively
|
|
34
|
-
from code_puppy.http_utils import find_available_port
|
|
35
|
-
from code_puppy.tools.common import console
|
|
36
|
-
|
|
37
|
-
# message_history_accumulator and prune_interrupted_tool_calls have been moved to BaseAgent class
|
|
38
|
-
from code_puppy.tui_state import is_tui_mode, set_tui_mode
|
|
39
|
-
from code_puppy.version_checker import default_version_mismatch_behavior
|
|
40
|
-
|
|
41
|
-
plugins.load_plugin_callbacks()
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
async def main():
|
|
45
|
-
parser = argparse.ArgumentParser(description="Code Puppy - A code generation agent")
|
|
46
|
-
parser.add_argument(
|
|
47
|
-
"--version",
|
|
48
|
-
"-v",
|
|
49
|
-
action="version",
|
|
50
|
-
version=f"{__version__}",
|
|
51
|
-
help="Show version and exit",
|
|
52
|
-
)
|
|
53
|
-
parser.add_argument(
|
|
54
|
-
"--interactive",
|
|
55
|
-
"-i",
|
|
56
|
-
action="store_true",
|
|
57
|
-
help="Run in interactive mode",
|
|
58
|
-
)
|
|
59
|
-
parser.add_argument("--tui", "-t", action="store_true", help="Run in TUI mode")
|
|
60
|
-
parser.add_argument(
|
|
61
|
-
"--web",
|
|
62
|
-
"-w",
|
|
63
|
-
action="store_true",
|
|
64
|
-
help="Run in web mode (serves TUI in browser)",
|
|
65
|
-
)
|
|
66
|
-
parser.add_argument(
|
|
67
|
-
"--prompt",
|
|
68
|
-
"-p",
|
|
69
|
-
type=str,
|
|
70
|
-
help="Execute a single prompt and exit (no interactive mode)",
|
|
71
|
-
)
|
|
72
|
-
parser.add_argument(
|
|
73
|
-
"--agent",
|
|
74
|
-
"-a",
|
|
75
|
-
type=str,
|
|
76
|
-
help="Specify which agent to use (e.g., --agent code-puppy)",
|
|
77
|
-
)
|
|
78
|
-
parser.add_argument(
|
|
79
|
-
"command", nargs="*", help="Run a single command (deprecated, use -p instead)"
|
|
80
|
-
)
|
|
81
|
-
args = parser.parse_args()
|
|
82
|
-
|
|
83
|
-
if args.tui or args.web:
|
|
84
|
-
set_tui_mode(True)
|
|
85
|
-
elif args.interactive or args.command or args.prompt:
|
|
86
|
-
set_tui_mode(False)
|
|
87
|
-
|
|
88
|
-
message_renderer = None
|
|
89
|
-
if not is_tui_mode():
|
|
90
|
-
from rich.console import Console
|
|
91
|
-
|
|
92
|
-
from code_puppy.messaging import (
|
|
93
|
-
SynchronousInteractiveRenderer,
|
|
94
|
-
get_global_queue,
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
message_queue = get_global_queue()
|
|
98
|
-
display_console = Console() # Separate console for rendering messages
|
|
99
|
-
message_renderer = SynchronousInteractiveRenderer(
|
|
100
|
-
message_queue, display_console
|
|
101
|
-
)
|
|
102
|
-
message_renderer.start()
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
not args.tui
|
|
106
|
-
and not args.interactive
|
|
107
|
-
and not args.web
|
|
108
|
-
and not args.command
|
|
109
|
-
and not args.prompt
|
|
110
|
-
):
|
|
111
|
-
pass
|
|
112
|
-
|
|
113
|
-
initialize_command_history_file()
|
|
114
|
-
if args.web:
|
|
115
|
-
from rich.console import Console
|
|
116
|
-
|
|
117
|
-
direct_console = Console()
|
|
118
|
-
try:
|
|
119
|
-
# Find an available port for the web server
|
|
120
|
-
available_port = find_available_port()
|
|
121
|
-
if available_port is None:
|
|
122
|
-
direct_console.print(
|
|
123
|
-
"[bold red]Error:[/bold red] No available ports in range 8090-9010!"
|
|
124
|
-
)
|
|
125
|
-
sys.exit(1)
|
|
126
|
-
python_executable = sys.executable
|
|
127
|
-
serve_command = f"{python_executable} -m code_puppy --tui"
|
|
128
|
-
textual_serve_cmd = [
|
|
129
|
-
"textual",
|
|
130
|
-
"serve",
|
|
131
|
-
"-c",
|
|
132
|
-
serve_command,
|
|
133
|
-
"--port",
|
|
134
|
-
str(available_port),
|
|
135
|
-
]
|
|
136
|
-
direct_console.print(
|
|
137
|
-
"[bold blue]🌐 Starting Code Puppy web interface...[/bold blue]"
|
|
138
|
-
)
|
|
139
|
-
direct_console.print(f"[dim]Running: {' '.join(textual_serve_cmd)}[/dim]")
|
|
140
|
-
web_url = f"http://localhost:{available_port}"
|
|
141
|
-
direct_console.print(
|
|
142
|
-
f"[green]Web interface will be available at: {web_url}[/green]"
|
|
143
|
-
)
|
|
144
|
-
direct_console.print("[yellow]Press Ctrl+C to stop the server.[/yellow]\n")
|
|
145
|
-
process = subprocess.Popen(textual_serve_cmd)
|
|
146
|
-
time.sleep(0.3)
|
|
147
|
-
try:
|
|
148
|
-
direct_console.print(
|
|
149
|
-
"[cyan]🚀 Opening web interface in your default browser...[/cyan]"
|
|
150
|
-
)
|
|
151
|
-
webbrowser.open(web_url)
|
|
152
|
-
direct_console.print("[green]✅ Browser opened successfully![/green]\n")
|
|
153
|
-
except Exception as e:
|
|
154
|
-
direct_console.print(
|
|
155
|
-
f"[yellow]⚠️ Could not automatically open browser: {e}[/yellow]"
|
|
156
|
-
)
|
|
157
|
-
direct_console.print(
|
|
158
|
-
f"[yellow]Please manually open: {web_url}[/yellow]\n"
|
|
159
|
-
)
|
|
160
|
-
result = process.wait()
|
|
161
|
-
sys.exit(result)
|
|
162
|
-
except Exception as e:
|
|
163
|
-
direct_console.print(
|
|
164
|
-
f"[bold red]Error starting web interface:[/bold red] {str(e)}"
|
|
165
|
-
)
|
|
166
|
-
sys.exit(1)
|
|
167
|
-
from code_puppy.messaging import emit_system_message
|
|
168
|
-
|
|
169
|
-
emit_system_message("🐶 Code Puppy is Loading...")
|
|
170
|
-
|
|
171
|
-
available_port = find_available_port()
|
|
172
|
-
if available_port is None:
|
|
173
|
-
error_msg = "Error: No available ports in range 8090-9010!"
|
|
174
|
-
emit_system_message(f"[bold red]{error_msg}[/bold red]")
|
|
175
|
-
return
|
|
176
|
-
|
|
177
|
-
ensure_config_exists()
|
|
178
|
-
|
|
179
|
-
# Handle agent selection from command line
|
|
180
|
-
if args.agent:
|
|
181
|
-
from code_puppy.agents.agent_manager import (
|
|
182
|
-
set_current_agent,
|
|
183
|
-
get_available_agents,
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
agent_name = args.agent.lower()
|
|
187
|
-
try:
|
|
188
|
-
# First check if the agent exists by getting available agents
|
|
189
|
-
available_agents = get_available_agents()
|
|
190
|
-
if agent_name not in available_agents:
|
|
191
|
-
emit_system_message(
|
|
192
|
-
f"[bold red]Error:[/bold red] Agent '{agent_name}' not found"
|
|
193
|
-
)
|
|
194
|
-
emit_system_message(
|
|
195
|
-
f"Available agents: {', '.join(available_agents.keys())}"
|
|
196
|
-
)
|
|
197
|
-
sys.exit(1)
|
|
198
|
-
|
|
199
|
-
# Agent exists, set it
|
|
200
|
-
set_current_agent(agent_name)
|
|
201
|
-
emit_system_message(f"🤖 Using agent: {agent_name}")
|
|
202
|
-
except Exception as e:
|
|
203
|
-
emit_system_message(f"[bold red]Error setting agent:[/bold red] {str(e)}")
|
|
204
|
-
sys.exit(1)
|
|
205
|
-
|
|
206
|
-
current_version = __version__
|
|
207
|
-
|
|
208
|
-
no_version_update = os.getenv("NO_VERSION_UPDATE", "").lower() in (
|
|
209
|
-
"1",
|
|
210
|
-
"true",
|
|
211
|
-
"yes",
|
|
212
|
-
"on",
|
|
213
|
-
)
|
|
214
|
-
if no_version_update:
|
|
215
|
-
version_msg = f"Current version: {current_version}"
|
|
216
|
-
update_disabled_msg = (
|
|
217
|
-
"Update phase disabled because NO_VERSION_UPDATE is set to 1 or true"
|
|
218
|
-
)
|
|
219
|
-
emit_system_message(version_msg)
|
|
220
|
-
emit_system_message(f"[dim]{update_disabled_msg}[/dim]")
|
|
221
|
-
else:
|
|
222
|
-
if len(callbacks.get_callbacks("version_check")):
|
|
223
|
-
await callbacks.on_version_check(current_version)
|
|
224
|
-
else:
|
|
225
|
-
default_version_mismatch_behavior(current_version)
|
|
226
|
-
|
|
227
|
-
await callbacks.on_startup()
|
|
228
|
-
|
|
229
|
-
# Initialize DBOS if not disabled
|
|
230
|
-
if get_use_dbos():
|
|
231
|
-
dbos_message = f"Initializing DBOS with database at: {DBOS_DATABASE_URL}"
|
|
232
|
-
emit_system_message(dbos_message)
|
|
233
|
-
|
|
234
|
-
dbos_config: DBOSConfig = {
|
|
235
|
-
"name": "dbos-code-puppy",
|
|
236
|
-
"system_database_url": DBOS_DATABASE_URL,
|
|
237
|
-
"run_admin_server": False,
|
|
238
|
-
"conductor_key": os.environ.get(
|
|
239
|
-
"DBOS_CONDUCTOR_KEY"
|
|
240
|
-
), # Optional, if set in env, connect to conductor
|
|
241
|
-
"log_level": os.environ.get(
|
|
242
|
-
"DBOS_LOG_LEVEL", "ERROR"
|
|
243
|
-
), # Default to ERROR level to suppress verbose logs
|
|
244
|
-
"application_version": current_version, # Match DBOS app version to Code Puppy version
|
|
245
|
-
}
|
|
246
|
-
try:
|
|
247
|
-
DBOS(config=dbos_config)
|
|
248
|
-
DBOS.launch()
|
|
249
|
-
except Exception as e:
|
|
250
|
-
emit_system_message(f"[bold red]Error initializing DBOS:[/bold red] {e}")
|
|
251
|
-
sys.exit(1)
|
|
252
|
-
else:
|
|
253
|
-
emit_system_message("DBOS is disabled. Running without durable execution.")
|
|
254
|
-
|
|
255
|
-
global shutdown_flag
|
|
256
|
-
shutdown_flag = False
|
|
257
|
-
try:
|
|
258
|
-
initial_command = None
|
|
259
|
-
prompt_only_mode = False
|
|
260
|
-
|
|
261
|
-
if args.prompt:
|
|
262
|
-
initial_command = args.prompt
|
|
263
|
-
prompt_only_mode = True
|
|
264
|
-
elif args.command:
|
|
265
|
-
initial_command = " ".join(args.command)
|
|
266
|
-
prompt_only_mode = False
|
|
267
|
-
|
|
268
|
-
if prompt_only_mode:
|
|
269
|
-
await execute_single_prompt(initial_command, message_renderer)
|
|
270
|
-
elif is_tui_mode():
|
|
271
|
-
try:
|
|
272
|
-
from code_puppy.tui import run_textual_ui
|
|
273
|
-
|
|
274
|
-
await run_textual_ui(initial_command=initial_command)
|
|
275
|
-
except ImportError:
|
|
276
|
-
from code_puppy.messaging import emit_error, emit_warning
|
|
277
|
-
|
|
278
|
-
emit_error(
|
|
279
|
-
"Error: Textual UI not available. Install with: pip install textual"
|
|
280
|
-
)
|
|
281
|
-
emit_warning("Falling back to interactive mode...")
|
|
282
|
-
await interactive_mode(message_renderer)
|
|
283
|
-
except Exception as e:
|
|
284
|
-
from code_puppy.messaging import emit_error, emit_warning
|
|
285
|
-
|
|
286
|
-
emit_error(f"TUI Error: {str(e)}")
|
|
287
|
-
emit_warning("Falling back to interactive mode...")
|
|
288
|
-
await interactive_mode(message_renderer)
|
|
289
|
-
elif args.interactive or initial_command:
|
|
290
|
-
await interactive_mode(message_renderer, initial_command=initial_command)
|
|
291
|
-
else:
|
|
292
|
-
await prompt_then_interactive_mode(message_renderer)
|
|
293
|
-
finally:
|
|
294
|
-
if message_renderer:
|
|
295
|
-
message_renderer.stop()
|
|
296
|
-
await callbacks.on_shutdown()
|
|
297
|
-
if get_use_dbos():
|
|
298
|
-
DBOS.destroy()
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
# Add the file handling functionality for interactive mode
|
|
302
|
-
async def interactive_mode(message_renderer, initial_command: str = None) -> None:
|
|
303
|
-
from code_puppy.command_line.command_handler import handle_command
|
|
304
|
-
|
|
305
|
-
"""Run the agent in interactive mode."""
|
|
306
|
-
|
|
307
|
-
display_console = message_renderer.console
|
|
308
|
-
from code_puppy.messaging import emit_info, emit_system_message
|
|
309
|
-
|
|
310
|
-
emit_info("[bold green]Code Puppy[/bold green] - Interactive Mode")
|
|
311
|
-
emit_system_message("Type '/exit' or '/quit' to exit the interactive mode.")
|
|
312
|
-
emit_system_message("Type 'clear' to reset the conversation history.")
|
|
313
|
-
emit_system_message("[dim]Type /help to view all commands[/dim]")
|
|
314
|
-
emit_system_message(
|
|
315
|
-
"Type [bold blue]@[/bold blue] for path completion, or [bold blue]/m[/bold blue] to pick a model. Toggle multiline with [bold blue]Alt+M[/bold blue] or [bold blue]F2[/bold blue]; newline: [bold blue]Ctrl+J[/bold blue]."
|
|
316
|
-
)
|
|
317
|
-
emit_system_message(
|
|
318
|
-
"Press [bold red]Ctrl+C[/bold red] during processing to cancel the current task or inference."
|
|
319
|
-
)
|
|
320
|
-
try:
|
|
321
|
-
from code_puppy.command_line.motd import print_motd
|
|
322
|
-
|
|
323
|
-
print_motd(console, force=False)
|
|
324
|
-
except Exception as e:
|
|
325
|
-
from code_puppy.messaging import emit_warning
|
|
326
|
-
|
|
327
|
-
emit_warning(f"MOTD error: {e}")
|
|
328
|
-
from code_puppy.messaging import emit_info
|
|
329
|
-
|
|
330
|
-
emit_info("[bold cyan]Initializing agent...[/bold cyan]")
|
|
331
|
-
|
|
332
|
-
# Initialize the runtime agent manager
|
|
333
|
-
if initial_command:
|
|
334
|
-
from code_puppy.agents import get_current_agent
|
|
335
|
-
from code_puppy.messaging import emit_info, emit_system_message
|
|
336
|
-
|
|
337
|
-
agent = get_current_agent()
|
|
338
|
-
emit_info(
|
|
339
|
-
f"[bold blue]Processing initial command:[/bold blue] {initial_command}"
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
try:
|
|
343
|
-
# Check if any tool is waiting for user input before showing spinner
|
|
344
|
-
try:
|
|
345
|
-
from code_puppy.tools.command_runner import is_awaiting_user_input
|
|
346
|
-
|
|
347
|
-
awaiting_input = is_awaiting_user_input()
|
|
348
|
-
except ImportError:
|
|
349
|
-
awaiting_input = False
|
|
350
|
-
|
|
351
|
-
# Run with or without spinner based on whether we're awaiting input
|
|
352
|
-
response = await run_prompt_with_attachments(
|
|
353
|
-
agent,
|
|
354
|
-
initial_command,
|
|
355
|
-
spinner_console=display_console,
|
|
356
|
-
use_spinner=not awaiting_input,
|
|
357
|
-
)
|
|
358
|
-
if response is not None:
|
|
359
|
-
agent_response = response.output
|
|
360
|
-
|
|
361
|
-
emit_system_message(
|
|
362
|
-
f"\n[bold purple]AGENT RESPONSE: [/bold purple]\n{agent_response}"
|
|
363
|
-
)
|
|
364
|
-
emit_system_message("\n" + "=" * 50)
|
|
365
|
-
emit_info("[bold green]🐶 Continuing in Interactive Mode[/bold green]")
|
|
366
|
-
emit_system_message(
|
|
367
|
-
"Your command and response are preserved in the conversation history."
|
|
368
|
-
)
|
|
369
|
-
emit_system_message("=" * 50 + "\n")
|
|
370
|
-
|
|
371
|
-
except Exception as e:
|
|
372
|
-
from code_puppy.messaging import emit_error
|
|
373
|
-
|
|
374
|
-
emit_error(f"Error processing initial command: {str(e)}")
|
|
375
|
-
|
|
376
|
-
# Check if prompt_toolkit is installed
|
|
377
|
-
try:
|
|
378
|
-
from code_puppy.messaging import emit_system_message
|
|
379
|
-
|
|
380
|
-
emit_system_message(
|
|
381
|
-
"[dim]Using prompt_toolkit for enhanced tab completion[/dim]"
|
|
382
|
-
)
|
|
383
|
-
except ImportError:
|
|
384
|
-
from code_puppy.messaging import emit_warning
|
|
385
|
-
|
|
386
|
-
emit_warning("Warning: prompt_toolkit not installed. Installing now...")
|
|
387
|
-
try:
|
|
388
|
-
import subprocess
|
|
389
|
-
|
|
390
|
-
subprocess.check_call(
|
|
391
|
-
[sys.executable, "-m", "pip", "install", "prompt_toolkit"]
|
|
392
|
-
)
|
|
393
|
-
from code_puppy.messaging import emit_success
|
|
394
|
-
|
|
395
|
-
emit_success("Successfully installed prompt_toolkit")
|
|
396
|
-
except Exception as e:
|
|
397
|
-
from code_puppy.messaging import emit_error, emit_warning
|
|
398
|
-
|
|
399
|
-
emit_error(f"Error installing prompt_toolkit: {e}")
|
|
400
|
-
emit_warning("Falling back to basic input without tab completion")
|
|
401
|
-
|
|
402
|
-
await restore_autosave_interactively(Path(AUTOSAVE_DIR))
|
|
403
|
-
|
|
404
|
-
while True:
|
|
405
|
-
from code_puppy.agents.agent_manager import get_current_agent
|
|
406
|
-
from code_puppy.messaging import emit_info
|
|
407
|
-
|
|
408
|
-
# Get the custom prompt from the current agent, or use default
|
|
409
|
-
current_agent = get_current_agent()
|
|
410
|
-
user_prompt = current_agent.get_user_prompt() or "Enter your coding task:"
|
|
411
|
-
|
|
412
|
-
emit_info(f"[bold blue]{user_prompt}[/bold blue]")
|
|
413
|
-
|
|
414
|
-
try:
|
|
415
|
-
# Use prompt_toolkit for enhanced input with path completion
|
|
416
|
-
try:
|
|
417
|
-
# Use the async version of get_input_with_combined_completion
|
|
418
|
-
task = await get_input_with_combined_completion(
|
|
419
|
-
get_prompt_with_active_model(), history_file=COMMAND_HISTORY_FILE
|
|
420
|
-
)
|
|
421
|
-
except ImportError:
|
|
422
|
-
# Fall back to basic input if prompt_toolkit is not available
|
|
423
|
-
task = input(">>> ")
|
|
424
|
-
|
|
425
|
-
except (KeyboardInterrupt, EOFError):
|
|
426
|
-
# Handle Ctrl+C or Ctrl+D
|
|
427
|
-
from code_puppy.messaging import emit_warning
|
|
428
|
-
|
|
429
|
-
emit_warning("\nInput cancelled")
|
|
430
|
-
continue
|
|
431
|
-
|
|
432
|
-
# Check for exit commands (plain text or command form)
|
|
433
|
-
if task.strip().lower() in ["exit", "quit"] or task.strip().lower() in [
|
|
434
|
-
"/exit",
|
|
435
|
-
"/quit",
|
|
436
|
-
]:
|
|
437
|
-
from code_puppy.messaging import emit_success
|
|
438
|
-
|
|
439
|
-
emit_success("Goodbye!")
|
|
440
|
-
# The renderer is stopped in the finally block of main().
|
|
441
|
-
break
|
|
442
|
-
|
|
443
|
-
# Check for clear command (supports both `clear` and `/clear`)
|
|
444
|
-
if task.strip().lower() in ("clear", "/clear"):
|
|
445
|
-
from code_puppy.messaging import (
|
|
446
|
-
emit_info,
|
|
447
|
-
emit_system_message,
|
|
448
|
-
emit_warning,
|
|
449
|
-
)
|
|
450
|
-
|
|
451
|
-
agent = get_current_agent()
|
|
452
|
-
new_session_id = finalize_autosave_session()
|
|
453
|
-
agent.clear_message_history()
|
|
454
|
-
emit_warning("Conversation history cleared!")
|
|
455
|
-
emit_system_message("The agent will not remember previous interactions.\n")
|
|
456
|
-
emit_info(f"[dim]Auto-save session rotated to: {new_session_id}[/dim]")
|
|
457
|
-
continue
|
|
458
|
-
|
|
459
|
-
# Parse attachments first so leading paths aren't misread as commands
|
|
460
|
-
processed_for_commands = parse_prompt_attachments(task)
|
|
461
|
-
cleaned_for_commands = (processed_for_commands.prompt or "").strip()
|
|
462
|
-
|
|
463
|
-
# Handle / commands based on cleaned prompt (after stripping attachments)
|
|
464
|
-
if cleaned_for_commands.startswith("/"):
|
|
465
|
-
try:
|
|
466
|
-
command_result = handle_command(cleaned_for_commands)
|
|
467
|
-
except Exception as e:
|
|
468
|
-
from code_puppy.messaging import emit_error
|
|
469
|
-
|
|
470
|
-
emit_error(f"Command error: {e}")
|
|
471
|
-
# Continue interactive loop instead of exiting
|
|
472
|
-
continue
|
|
473
|
-
if command_result is True:
|
|
474
|
-
continue
|
|
475
|
-
elif isinstance(command_result, str):
|
|
476
|
-
# Command returned a prompt to execute
|
|
477
|
-
task = command_result
|
|
478
|
-
elif command_result is False:
|
|
479
|
-
# Command not recognized, continue with normal processing
|
|
480
|
-
pass
|
|
481
|
-
|
|
482
|
-
if task.strip():
|
|
483
|
-
# Write to the secret file for permanent history with timestamp
|
|
484
|
-
save_command_to_history(task)
|
|
485
|
-
|
|
486
|
-
try:
|
|
487
|
-
prettier_code_blocks()
|
|
488
|
-
|
|
489
|
-
# No need to get agent directly - use manager's run methods
|
|
490
|
-
|
|
491
|
-
# Use our custom helper to enable attachment handling with spinner support
|
|
492
|
-
result = await run_prompt_with_attachments(
|
|
493
|
-
current_agent,
|
|
494
|
-
task,
|
|
495
|
-
spinner_console=message_renderer.console,
|
|
496
|
-
)
|
|
497
|
-
# Check if the task was cancelled (but don't show message if we just killed processes)
|
|
498
|
-
if result is None:
|
|
499
|
-
continue
|
|
500
|
-
# Get the structured response
|
|
501
|
-
agent_response = result.output
|
|
502
|
-
from code_puppy.messaging import emit_info
|
|
503
|
-
|
|
504
|
-
emit_system_message(
|
|
505
|
-
f"\n[bold purple]AGENT RESPONSE: [/bold purple]\n{agent_response}"
|
|
506
|
-
)
|
|
507
|
-
|
|
508
|
-
# Auto-save session if enabled
|
|
509
|
-
from code_puppy.config import auto_save_session_if_enabled
|
|
510
|
-
|
|
511
|
-
auto_save_session_if_enabled()
|
|
512
|
-
|
|
513
|
-
# Ensure console output is flushed before next prompt
|
|
514
|
-
# This fixes the issue where prompt doesn't appear after agent response
|
|
515
|
-
display_console.file.flush() if hasattr(
|
|
516
|
-
display_console.file, "flush"
|
|
517
|
-
) else None
|
|
518
|
-
import time
|
|
519
|
-
|
|
520
|
-
time.sleep(0.1) # Brief pause to ensure all messages are rendered
|
|
521
|
-
|
|
522
|
-
except Exception:
|
|
523
|
-
from code_puppy.messaging.queue_console import get_queue_console
|
|
524
|
-
|
|
525
|
-
get_queue_console().print_exception()
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
def prettier_code_blocks():
|
|
529
|
-
class SimpleCodeBlock(CodeBlock):
|
|
530
|
-
def __rich_console__(
|
|
531
|
-
self, console: Console, options: ConsoleOptions
|
|
532
|
-
) -> RenderResult:
|
|
533
|
-
code = str(self.text).rstrip()
|
|
534
|
-
yield Text(self.lexer_name, style="dim")
|
|
535
|
-
syntax = Syntax(
|
|
536
|
-
code,
|
|
537
|
-
self.lexer_name,
|
|
538
|
-
theme=self.theme,
|
|
539
|
-
background_color="default",
|
|
540
|
-
line_numbers=True,
|
|
541
|
-
)
|
|
542
|
-
yield syntax
|
|
543
|
-
yield Text(f"/{self.lexer_name}", style="dim")
|
|
544
|
-
|
|
545
|
-
Markdown.elements["fence"] = SimpleCodeBlock
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
async def run_prompt_with_attachments(
|
|
549
|
-
agent,
|
|
550
|
-
raw_prompt: str,
|
|
551
|
-
*,
|
|
552
|
-
spinner_console=None,
|
|
553
|
-
use_spinner: bool = True,
|
|
554
|
-
):
|
|
555
|
-
"""Run the agent after parsing CLI attachments for image/document support."""
|
|
556
|
-
from code_puppy.messaging import emit_system_message, emit_warning
|
|
557
|
-
|
|
558
|
-
processed_prompt = parse_prompt_attachments(raw_prompt)
|
|
559
|
-
|
|
560
|
-
for warning in processed_prompt.warnings:
|
|
561
|
-
emit_warning(warning)
|
|
562
|
-
|
|
563
|
-
summary_parts = []
|
|
564
|
-
if processed_prompt.attachments:
|
|
565
|
-
summary_parts.append(f"binary files: {len(processed_prompt.attachments)}")
|
|
566
|
-
if processed_prompt.link_attachments:
|
|
567
|
-
summary_parts.append(f"urls: {len(processed_prompt.link_attachments)}")
|
|
568
|
-
if summary_parts:
|
|
569
|
-
emit_system_message(
|
|
570
|
-
"[dim]Attachments detected -> " + ", ".join(summary_parts) + "[/dim]"
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
if not processed_prompt.prompt:
|
|
574
|
-
emit_warning(
|
|
575
|
-
"Prompt is empty after removing attachments; add instructions and retry."
|
|
576
|
-
)
|
|
577
|
-
return None
|
|
578
|
-
|
|
579
|
-
attachments = [attachment.content for attachment in processed_prompt.attachments]
|
|
580
|
-
link_attachments = [link.url_part for link in processed_prompt.link_attachments]
|
|
581
|
-
|
|
582
|
-
if use_spinner and spinner_console is not None:
|
|
583
|
-
from code_puppy.messaging.spinner import ConsoleSpinner
|
|
584
|
-
|
|
585
|
-
with ConsoleSpinner(console=spinner_console):
|
|
586
|
-
return await agent.run_with_mcp(
|
|
587
|
-
processed_prompt.prompt,
|
|
588
|
-
attachments=attachments,
|
|
589
|
-
link_attachments=link_attachments,
|
|
590
|
-
)
|
|
591
|
-
|
|
592
|
-
return await agent.run_with_mcp(
|
|
593
|
-
processed_prompt.prompt,
|
|
594
|
-
attachments=attachments,
|
|
595
|
-
link_attachments=link_attachments,
|
|
596
|
-
)
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
async def execute_single_prompt(prompt: str, message_renderer) -> None:
|
|
600
|
-
"""Execute a single prompt and exit (for -p flag)."""
|
|
601
|
-
from code_puppy.messaging import emit_info, emit_system_message
|
|
602
|
-
|
|
603
|
-
emit_info(f"[bold blue]Executing prompt:[/bold blue] {prompt}")
|
|
604
|
-
|
|
605
|
-
try:
|
|
606
|
-
# Get agent through runtime manager and use helper for attachments
|
|
607
|
-
agent = get_current_agent()
|
|
608
|
-
response = await run_prompt_with_attachments(
|
|
609
|
-
agent,
|
|
610
|
-
prompt,
|
|
611
|
-
spinner_console=message_renderer.console,
|
|
612
|
-
)
|
|
613
|
-
if response is None:
|
|
614
|
-
return
|
|
615
|
-
|
|
616
|
-
agent_response = response.output
|
|
617
|
-
emit_system_message(
|
|
618
|
-
f"\n[bold purple]AGENT RESPONSE: [/bold purple]\n{agent_response}"
|
|
619
|
-
)
|
|
620
|
-
|
|
621
|
-
except asyncio.CancelledError:
|
|
622
|
-
from code_puppy.messaging import emit_warning
|
|
623
|
-
|
|
624
|
-
emit_warning("Execution cancelled by user")
|
|
625
|
-
except Exception as e:
|
|
626
|
-
from code_puppy.messaging import emit_error
|
|
627
|
-
|
|
628
|
-
emit_error(f"Error executing prompt: {str(e)}")
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
async def prompt_then_interactive_mode(message_renderer) -> None:
|
|
632
|
-
"""Prompt user for input, execute it, then continue in interactive mode."""
|
|
633
|
-
from code_puppy.messaging import emit_info, emit_system_message
|
|
634
|
-
|
|
635
|
-
emit_info("[bold green]🐶 Code Puppy[/bold green] - Enter your request")
|
|
636
|
-
emit_system_message(
|
|
637
|
-
"After processing your request, you'll continue in interactive mode."
|
|
638
|
-
)
|
|
639
|
-
|
|
640
|
-
try:
|
|
641
|
-
# Get user input
|
|
642
|
-
from code_puppy.command_line.prompt_toolkit_completion import (
|
|
643
|
-
get_input_with_combined_completion,
|
|
644
|
-
get_prompt_with_active_model,
|
|
645
|
-
)
|
|
646
|
-
from code_puppy.config import COMMAND_HISTORY_FILE
|
|
647
|
-
|
|
648
|
-
emit_info("[bold blue]What would you like me to help you with?[/bold blue]")
|
|
649
|
-
|
|
650
|
-
try:
|
|
651
|
-
# Use prompt_toolkit for enhanced input with path completion
|
|
652
|
-
user_prompt = await get_input_with_combined_completion(
|
|
653
|
-
get_prompt_with_active_model(), history_file=COMMAND_HISTORY_FILE
|
|
654
|
-
)
|
|
655
|
-
except ImportError:
|
|
656
|
-
# Fall back to basic input if prompt_toolkit is not available
|
|
657
|
-
user_prompt = input(">>> ")
|
|
658
|
-
|
|
659
|
-
if user_prompt.strip():
|
|
660
|
-
# Execute the prompt
|
|
661
|
-
await execute_single_prompt(user_prompt, message_renderer)
|
|
662
|
-
|
|
663
|
-
# Transition to interactive mode
|
|
664
|
-
emit_system_message("\n" + "=" * 50)
|
|
665
|
-
emit_info("[bold green]🐶 Continuing in Interactive Mode[/bold green]")
|
|
666
|
-
emit_system_message(
|
|
667
|
-
"Your request and response are preserved in the conversation history."
|
|
668
|
-
)
|
|
669
|
-
emit_system_message("=" * 50 + "\n")
|
|
670
|
-
|
|
671
|
-
# Continue in interactive mode with the initial command as history
|
|
672
|
-
await interactive_mode(message_renderer, initial_command=user_prompt)
|
|
673
|
-
else:
|
|
674
|
-
# No input provided, just go to interactive mode
|
|
675
|
-
await interactive_mode(message_renderer)
|
|
676
|
-
|
|
677
|
-
except (KeyboardInterrupt, EOFError):
|
|
678
|
-
from code_puppy.messaging import emit_warning
|
|
679
|
-
|
|
680
|
-
emit_warning("\nInput cancelled. Starting interactive mode...")
|
|
681
|
-
await interactive_mode(message_renderer)
|
|
682
|
-
except Exception as e:
|
|
683
|
-
from code_puppy.messaging import emit_error
|
|
684
|
-
|
|
685
|
-
emit_error(f"Error in prompt mode: {str(e)}")
|
|
686
|
-
emit_info("Falling back to interactive mode...")
|
|
687
|
-
await interactive_mode(message_renderer)
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
def main_entry():
|
|
691
|
-
"""Entry point for the installed CLI tool."""
|
|
692
|
-
try:
|
|
693
|
-
asyncio.run(main())
|
|
694
|
-
except KeyboardInterrupt:
|
|
695
|
-
# Just exit gracefully with no error message
|
|
696
|
-
callbacks.on_shutdown()
|
|
697
|
-
if get_use_dbos():
|
|
698
|
-
DBOS.destroy()
|
|
699
|
-
return 0
|
|
3
|
+
This module re-exports the main_entry function from cli_runner for backwards compatibility.
|
|
4
|
+
All the actual logic lives in cli_runner.py.
|
|
5
|
+
"""
|
|
700
6
|
|
|
7
|
+
from code_puppy.cli_runner import main_entry
|
|
701
8
|
|
|
702
9
|
if __name__ == "__main__":
|
|
703
10
|
main_entry()
|