code-puppy 0.0.169__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 +8 -8
- code_puppy/agents/agent_c_reviewer.py +155 -0
- code_puppy/agents/agent_code_puppy.py +9 -2
- code_puppy/agents/agent_code_reviewer.py +90 -0
- code_puppy/agents/agent_cpp_reviewer.py +132 -0
- code_puppy/agents/agent_creator_agent.py +48 -9
- code_puppy/agents/agent_golang_reviewer.py +151 -0
- code_puppy/agents/agent_javascript_reviewer.py +160 -0
- code_puppy/agents/agent_manager.py +146 -199
- 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 +90 -0
- code_puppy/agents/agent_qa_expert.py +163 -0
- code_puppy/agents/agent_qa_kitten.py +208 -0
- code_puppy/agents/agent_security_auditor.py +181 -0
- code_puppy/agents/agent_terminal_qa.py +323 -0
- code_puppy/agents/agent_typescript_reviewer.py +166 -0
- code_puppy/agents/base_agent.py +1713 -1
- code_puppy/agents/event_stream_handler.py +350 -0
- code_puppy/agents/json_agent.py +12 -1
- 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 +174 -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 +395 -0
- 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 +233 -627
- 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 +1 -4
- 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 +16 -27
- code_puppy/command_line/mcp/install_menu.py +685 -0
- code_puppy/command_line/mcp/list_command.py +3 -3
- 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 +17 -11
- code_puppy/command_line/mcp/start_all_command.py +22 -13
- code_puppy/command_line/mcp/start_command.py +50 -31
- code_puppy/command_line/mcp/status_command.py +6 -7
- code_puppy/command_line/mcp/stop_all_command.py +11 -8
- code_puppy/command_line/mcp/stop_command.py +11 -10
- code_puppy/command_line/mcp/test_command.py +2 -2
- code_puppy/command_line/mcp/utils.py +1 -1
- code_puppy/command_line/mcp/wizard_utils.py +22 -18
- code_puppy/command_line/mcp_completion.py +174 -0
- code_puppy/command_line/model_picker_completion.py +89 -30
- 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 +626 -75
- code_puppy/command_line/session_commands.py +296 -0
- code_puppy/command_line/utils.py +54 -0
- code_puppy/config.py +1181 -51
- 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 +220 -104
- code_puppy/keymap.py +128 -0
- code_puppy/main.py +5 -594
- code_puppy/{mcp → mcp_}/__init__.py +17 -0
- code_puppy/{mcp → mcp_}/async_lifecycle.py +35 -4
- code_puppy/{mcp → mcp_}/blocking_startup.py +70 -43
- code_puppy/{mcp → mcp_}/captured_stdio_server.py +2 -2
- code_puppy/{mcp → mcp_}/config_wizard.py +5 -5
- code_puppy/{mcp → mcp_}/dashboard.py +15 -6
- code_puppy/{mcp → mcp_}/examples/retry_example.py +4 -1
- code_puppy/{mcp → mcp_}/managed_server.py +66 -39
- code_puppy/{mcp → mcp_}/manager.py +146 -52
- code_puppy/mcp_/mcp_logs.py +224 -0
- code_puppy/{mcp → mcp_}/registry.py +6 -6
- code_puppy/{mcp → mcp_}/server_registry_catalog.py +25 -8
- 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 +33 -5
- code_puppy/messaging/spinner/console_spinner.py +92 -52
- code_puppy/messaging/spinner/spinner_base.py +29 -0
- code_puppy/messaging/subagent_console.py +461 -0
- code_puppy/model_factory.py +686 -80
- code_puppy/model_utils.py +167 -0
- code_puppy/models.json +86 -104
- 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 +51 -0
- 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 +10 -15
- code_puppy/session_storage.py +294 -0
- code_puppy/status_display.py +21 -4
- code_puppy/summarization_agent.py +52 -14
- code_puppy/terminal_utils.py +418 -0
- code_puppy/tools/__init__.py +139 -6
- code_puppy/tools/agent_tools.py +548 -49
- code_puppy/tools/browser/__init__.py +37 -0
- code_puppy/tools/browser/browser_control.py +289 -0
- code_puppy/tools/browser/browser_interactions.py +545 -0
- code_puppy/tools/browser/browser_locators.py +640 -0
- code_puppy/tools/browser/browser_manager.py +316 -0
- code_puppy/tools/browser/browser_navigation.py +251 -0
- code_puppy/tools/browser/browser_screenshot.py +179 -0
- code_puppy/tools/browser/browser_scripts.py +462 -0
- code_puppy/tools/browser/browser_workflows.py +221 -0
- 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 +941 -153
- code_puppy/tools/common.py +1146 -6
- code_puppy/tools/display.py +84 -0
- code_puppy/tools/file_modifications.py +288 -89
- code_puppy/tools/file_operations.py +352 -266
- 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.169.dist-info → code_puppy-0.0.366.dist-info}/METADATA +184 -67
- code_puppy-0.0.366.dist-info/RECORD +217 -0
- {code_puppy-0.0.169.dist-info → code_puppy-0.0.366.dist-info}/WHEEL +1 -1
- {code_puppy-0.0.169.dist-info → code_puppy-0.0.366.dist-info}/entry_points.txt +1 -0
- code_puppy/agent.py +0 -231
- code_puppy/agents/agent_orchestrator.json +0 -26
- code_puppy/agents/runtime_manager.py +0 -272
- code_puppy/command_line/mcp/add_command.py +0 -183
- code_puppy/command_line/meta_command_handler.py +0 -153
- code_puppy/message_history_processor.py +0 -490
- code_puppy/messaging/spinner/textual_spinner.py +0 -101
- code_puppy/state_management.py +0 -200
- code_puppy/tui/__init__.py +0 -10
- code_puppy/tui/app.py +0 -986
- code_puppy/tui/components/__init__.py +0 -21
- code_puppy/tui/components/chat_view.py +0 -550
- 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 -182
- 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 -15
- 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 -290
- code_puppy/tui/screens/tools.py +0 -74
- code_puppy-0.0.169.data/data/code_puppy/models.json +0 -128
- code_puppy-0.0.169.dist-info/RECORD +0 -112
- /code_puppy/{mcp → mcp_}/circuit_breaker.py +0 -0
- /code_puppy/{mcp → mcp_}/error_isolation.py +0 -0
- /code_puppy/{mcp → mcp_}/health_monitor.py +0 -0
- /code_puppy/{mcp → mcp_}/retry_manager.py +0 -0
- /code_puppy/{mcp → mcp_}/status_tracker.py +0 -0
- /code_puppy/{mcp → mcp_}/system_tools.py +0 -0
- {code_puppy-0.0.169.dist-info → code_puppy-0.0.366.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Command models for User → Agent communication in Code Puppy's messaging system.
|
|
2
|
+
|
|
3
|
+
This module defines Pydantic models for commands that flow FROM the UI TO the Agent.
|
|
4
|
+
This is the opposite direction of messages.py (which flows Agent → UI).
|
|
5
|
+
|
|
6
|
+
Commands are used for:
|
|
7
|
+
- Controlling agent execution (cancel, interrupt)
|
|
8
|
+
- Responding to agent requests for user input
|
|
9
|
+
- Providing confirmations and selections
|
|
10
|
+
|
|
11
|
+
The UI layer creates these commands and sends them to the agent/runtime.
|
|
12
|
+
The agent processes them and may emit messages in response.
|
|
13
|
+
|
|
14
|
+
┌─────────┐ Commands ┌─────────┐
|
|
15
|
+
│ UI │ ────────────> │ Agent │
|
|
16
|
+
│ (User) │ │ │
|
|
17
|
+
│ │ <──────────── │ │
|
|
18
|
+
└─────────┘ Messages └─────────┘
|
|
19
|
+
|
|
20
|
+
NO Rich markup or formatting should be embedded in any string fields.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
|
+
from typing import Optional, Union
|
|
25
|
+
from uuid import uuid4
|
|
26
|
+
|
|
27
|
+
from pydantic import BaseModel, Field
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# Base Command
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BaseCommand(BaseModel):
|
|
35
|
+
"""Base class for all commands with auto-generated id and timestamp."""
|
|
36
|
+
|
|
37
|
+
id: str = Field(
|
|
38
|
+
default_factory=lambda: str(uuid4()),
|
|
39
|
+
description="Unique identifier for this command instance",
|
|
40
|
+
)
|
|
41
|
+
timestamp: datetime = Field(
|
|
42
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
43
|
+
description="When this command was created (UTC)",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
model_config = {"frozen": False, "extra": "forbid"}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# =============================================================================
|
|
50
|
+
# Agent Control Commands
|
|
51
|
+
# =============================================================================
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CancelAgentCommand(BaseCommand):
|
|
55
|
+
"""Signals the agent to stop current execution gracefully.
|
|
56
|
+
|
|
57
|
+
The agent should finish any in-progress atomic operation, clean up,
|
|
58
|
+
and return control to the user. This is a soft cancellation.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
reason: Optional[str] = Field(
|
|
62
|
+
default=None,
|
|
63
|
+
description="Optional reason for cancellation (for logging/debugging)",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class InterruptShellCommand(BaseCommand):
|
|
68
|
+
"""Signals to interrupt a currently running shell command.
|
|
69
|
+
|
|
70
|
+
This is equivalent to pressing Ctrl+C in a terminal. The shell process
|
|
71
|
+
should receive SIGINT and terminate. Use this when a command is taking
|
|
72
|
+
too long or producing unwanted output.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
command_id: Optional[str] = Field(
|
|
76
|
+
default=None,
|
|
77
|
+
description="ID of the specific shell command to interrupt (None = current)",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# =============================================================================
|
|
82
|
+
# User Interaction Responses
|
|
83
|
+
# =============================================================================
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class UserInputResponse(BaseCommand):
|
|
87
|
+
"""Response to a UserInputRequest from the agent.
|
|
88
|
+
|
|
89
|
+
The prompt_id must match the prompt_id from the original UserInputRequest
|
|
90
|
+
so the agent can correlate the response with the request.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
prompt_id: str = Field(
|
|
94
|
+
description="ID of the prompt this responds to (must match request)"
|
|
95
|
+
)
|
|
96
|
+
value: str = Field(description="The user's input value")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ConfirmationResponse(BaseCommand):
|
|
100
|
+
"""Response to a ConfirmationRequest from the agent.
|
|
101
|
+
|
|
102
|
+
The user can confirm or deny, and optionally provide feedback text
|
|
103
|
+
if the original request had allow_feedback=True.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
prompt_id: str = Field(
|
|
107
|
+
description="ID of the prompt this responds to (must match request)"
|
|
108
|
+
)
|
|
109
|
+
confirmed: bool = Field(
|
|
110
|
+
description="Whether the user confirmed (True) or denied (False)"
|
|
111
|
+
)
|
|
112
|
+
feedback: Optional[str] = Field(
|
|
113
|
+
default=None,
|
|
114
|
+
description="Optional feedback text from the user",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class SelectionResponse(BaseCommand):
|
|
119
|
+
"""Response to a SelectionRequest from the agent.
|
|
120
|
+
|
|
121
|
+
Contains both the index and the value for convenience and validation.
|
|
122
|
+
The agent can verify that selected_value matches options[selected_index].
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
prompt_id: str = Field(
|
|
126
|
+
description="ID of the prompt this responds to (must match request)"
|
|
127
|
+
)
|
|
128
|
+
selected_index: int = Field(
|
|
129
|
+
ge=0,
|
|
130
|
+
description="Zero-based index of the selected option",
|
|
131
|
+
)
|
|
132
|
+
selected_value: str = Field(description="The value of the selected option")
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# =============================================================================
|
|
136
|
+
# Union Type for Type Checking
|
|
137
|
+
# =============================================================================
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# All concrete command types (excludes BaseCommand itself)
|
|
141
|
+
AnyCommand = Union[
|
|
142
|
+
CancelAgentCommand,
|
|
143
|
+
InterruptShellCommand,
|
|
144
|
+
UserInputResponse,
|
|
145
|
+
ConfirmationResponse,
|
|
146
|
+
SelectionResponse,
|
|
147
|
+
]
|
|
148
|
+
"""Union of all command types for type checking."""
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# =============================================================================
|
|
152
|
+
# Export all public symbols
|
|
153
|
+
# =============================================================================
|
|
154
|
+
|
|
155
|
+
__all__ = [
|
|
156
|
+
# Base
|
|
157
|
+
"BaseCommand",
|
|
158
|
+
# Agent control
|
|
159
|
+
"CancelAgentCommand",
|
|
160
|
+
"InterruptShellCommand",
|
|
161
|
+
# User interaction responses
|
|
162
|
+
"UserInputResponse",
|
|
163
|
+
"ConfirmationResponse",
|
|
164
|
+
"SelectionResponse",
|
|
165
|
+
# Union type
|
|
166
|
+
"AnyCommand",
|
|
167
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Patches for Rich's Markdown rendering.
|
|
2
|
+
|
|
3
|
+
This module provides customizations to Rich's default Markdown rendering,
|
|
4
|
+
particularly for header justification which is hardcoded to center in Rich.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from rich import box
|
|
8
|
+
from rich.markdown import Heading, Markdown
|
|
9
|
+
from rich.panel import Panel
|
|
10
|
+
from rich.text import Text
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LeftJustifiedHeading(Heading):
|
|
14
|
+
"""A heading that left-justifies text instead of centering.
|
|
15
|
+
|
|
16
|
+
Rich's default Heading class hardcodes `text.justify = 'center'`,
|
|
17
|
+
which can look odd in a CLI context. This subclass overrides that
|
|
18
|
+
to use left justification instead.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __rich_console__(self, console, options):
|
|
22
|
+
"""Render the heading with left justification."""
|
|
23
|
+
text = self.text
|
|
24
|
+
text.justify = "left" # Override Rich's default 'center'
|
|
25
|
+
|
|
26
|
+
if self.tag == "h1":
|
|
27
|
+
# Draw a border around h1s (same as Rich default)
|
|
28
|
+
yield Panel(
|
|
29
|
+
text,
|
|
30
|
+
box=box.HEAVY,
|
|
31
|
+
style="markdown.h1.border",
|
|
32
|
+
)
|
|
33
|
+
else:
|
|
34
|
+
# Styled text for h2 and beyond (same as Rich default)
|
|
35
|
+
if self.tag == "h2":
|
|
36
|
+
yield Text("")
|
|
37
|
+
yield text
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
_patched = False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def patch_markdown_headings():
|
|
44
|
+
"""Patch Rich's Markdown to use left-justified headings.
|
|
45
|
+
|
|
46
|
+
This function is idempotent - calling it multiple times has no effect
|
|
47
|
+
after the first call.
|
|
48
|
+
"""
|
|
49
|
+
global _patched
|
|
50
|
+
if _patched:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
Markdown.elements["heading_open"] = LeftJustifiedHeading
|
|
54
|
+
_patched = True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
__all__ = ["patch_markdown_headings", "LeftJustifiedHeading"]
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Message queue system for decoupling Rich console output from renderers.
|
|
3
3
|
|
|
4
|
-
This allows
|
|
5
|
-
but render them differently based on their capabilities.
|
|
4
|
+
This allows interactive mode to consume messages and render them appropriately.
|
|
6
5
|
"""
|
|
7
6
|
|
|
8
7
|
import asyncio
|
|
@@ -218,35 +217,23 @@ class MessageQueue:
|
|
|
218
217
|
|
|
219
218
|
start_time = time.time()
|
|
220
219
|
|
|
221
|
-
#
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
sleep_interval = 0.05 if is_tui_mode() else 0.1
|
|
225
|
-
|
|
226
|
-
# Debug logging for TUI mode
|
|
227
|
-
if is_tui_mode():
|
|
228
|
-
print(f"[DEBUG] Waiting for prompt response: {prompt_id}")
|
|
220
|
+
# TUI mode has been removed, use standard sleep interval
|
|
221
|
+
sleep_interval = 0.1
|
|
229
222
|
|
|
230
223
|
while True:
|
|
231
224
|
if prompt_id in self._prompt_responses:
|
|
232
225
|
response = self._prompt_responses.pop(prompt_id)
|
|
233
|
-
if is_tui_mode():
|
|
234
|
-
print(f"[DEBUG] Got response for {prompt_id}: {response[:20]}...")
|
|
235
226
|
return response
|
|
236
227
|
|
|
237
228
|
if timeout and (time.time() - start_time) > timeout:
|
|
238
229
|
raise TimeoutError(
|
|
239
|
-
f"No response
|
|
230
|
+
f"No response for prompt {prompt_id} within {timeout}s"
|
|
240
231
|
)
|
|
241
232
|
|
|
242
233
|
time.sleep(sleep_interval)
|
|
243
234
|
|
|
244
235
|
def provide_prompt_response(self, prompt_id: str, response: str):
|
|
245
236
|
"""Provide a response to a human input request."""
|
|
246
|
-
from code_puppy.state_management import is_tui_mode
|
|
247
|
-
|
|
248
|
-
if is_tui_mode():
|
|
249
|
-
print(f"[DEBUG] Providing response for {prompt_id}: {response[:20]}...")
|
|
250
237
|
self._prompt_responses[prompt_id] = response
|
|
251
238
|
|
|
252
239
|
|
|
@@ -335,44 +322,26 @@ def emit_system_message(content: Any, **metadata):
|
|
|
335
322
|
emit_message(MessageType.SYSTEM, content, **metadata)
|
|
336
323
|
|
|
337
324
|
|
|
338
|
-
def emit_divider(content: str = "
|
|
325
|
+
def emit_divider(content: str = "─" * 100 + "\n", **metadata):
|
|
339
326
|
"""Emit a divider line"""
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if not is_tui_mode():
|
|
343
|
-
emit_message(MessageType.DIVIDER, content, **metadata)
|
|
344
|
-
else:
|
|
345
|
-
pass
|
|
327
|
+
# TUI mode has been removed, always emit dividers
|
|
328
|
+
emit_message(MessageType.DIVIDER, content, **metadata)
|
|
346
329
|
|
|
347
330
|
|
|
348
331
|
def emit_prompt(prompt_text: str, timeout: float = None) -> str:
|
|
349
|
-
"""Emit a human input request and wait for response.
|
|
350
|
-
from code_puppy.state_management import is_tui_mode
|
|
332
|
+
"""Emit a human input request and wait for response.
|
|
351
333
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
334
|
+
Uses safe_input for cross-platform compatibility, especially on Windows
|
|
335
|
+
where raw input() can fail after prompt_toolkit Applications.
|
|
336
|
+
"""
|
|
337
|
+
from code_puppy.command_line.utils import safe_input
|
|
338
|
+
from code_puppy.messaging import emit_info
|
|
356
339
|
|
|
357
|
-
|
|
340
|
+
emit_info(prompt_text)
|
|
358
341
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
from rich.console import Console
|
|
363
|
-
|
|
364
|
-
console = Console()
|
|
365
|
-
response = console.input("[cyan]>>> [/cyan]")
|
|
366
|
-
return response
|
|
367
|
-
except Exception:
|
|
368
|
-
# Fallback to basic input
|
|
369
|
-
response = input(">>> ")
|
|
370
|
-
return response
|
|
371
|
-
|
|
372
|
-
# In TUI mode, use the queue system
|
|
373
|
-
queue = get_global_queue()
|
|
374
|
-
prompt_id = queue.create_prompt_request(prompt_text)
|
|
375
|
-
return queue.wait_for_prompt_response(prompt_id, timeout)
|
|
342
|
+
# Use safe_input which resets Windows console state before reading
|
|
343
|
+
response = safe_input(">>> ")
|
|
344
|
+
return response
|
|
376
345
|
|
|
377
346
|
|
|
378
347
|
def provide_prompt_response(prompt_id: str, response: str):
|