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.
Files changed (243) hide show
  1. code_puppy/__init__.py +7 -1
  2. code_puppy/agents/__init__.py +8 -8
  3. code_puppy/agents/agent_c_reviewer.py +155 -0
  4. code_puppy/agents/agent_code_puppy.py +9 -2
  5. code_puppy/agents/agent_code_reviewer.py +90 -0
  6. code_puppy/agents/agent_cpp_reviewer.py +132 -0
  7. code_puppy/agents/agent_creator_agent.py +48 -9
  8. code_puppy/agents/agent_golang_reviewer.py +151 -0
  9. code_puppy/agents/agent_javascript_reviewer.py +160 -0
  10. code_puppy/agents/agent_manager.py +146 -199
  11. code_puppy/agents/agent_pack_leader.py +383 -0
  12. code_puppy/agents/agent_planning.py +163 -0
  13. code_puppy/agents/agent_python_programmer.py +165 -0
  14. code_puppy/agents/agent_python_reviewer.py +90 -0
  15. code_puppy/agents/agent_qa_expert.py +163 -0
  16. code_puppy/agents/agent_qa_kitten.py +208 -0
  17. code_puppy/agents/agent_security_auditor.py +181 -0
  18. code_puppy/agents/agent_terminal_qa.py +323 -0
  19. code_puppy/agents/agent_typescript_reviewer.py +166 -0
  20. code_puppy/agents/base_agent.py +1713 -1
  21. code_puppy/agents/event_stream_handler.py +350 -0
  22. code_puppy/agents/json_agent.py +12 -1
  23. code_puppy/agents/pack/__init__.py +34 -0
  24. code_puppy/agents/pack/bloodhound.py +304 -0
  25. code_puppy/agents/pack/husky.py +321 -0
  26. code_puppy/agents/pack/retriever.py +393 -0
  27. code_puppy/agents/pack/shepherd.py +348 -0
  28. code_puppy/agents/pack/terrier.py +287 -0
  29. code_puppy/agents/pack/watchdog.py +367 -0
  30. code_puppy/agents/prompt_reviewer.py +145 -0
  31. code_puppy/agents/subagent_stream_handler.py +276 -0
  32. code_puppy/api/__init__.py +13 -0
  33. code_puppy/api/app.py +169 -0
  34. code_puppy/api/main.py +21 -0
  35. code_puppy/api/pty_manager.py +446 -0
  36. code_puppy/api/routers/__init__.py +12 -0
  37. code_puppy/api/routers/agents.py +36 -0
  38. code_puppy/api/routers/commands.py +217 -0
  39. code_puppy/api/routers/config.py +74 -0
  40. code_puppy/api/routers/sessions.py +232 -0
  41. code_puppy/api/templates/terminal.html +361 -0
  42. code_puppy/api/websocket.py +154 -0
  43. code_puppy/callbacks.py +174 -4
  44. code_puppy/chatgpt_codex_client.py +283 -0
  45. code_puppy/claude_cache_client.py +586 -0
  46. code_puppy/cli_runner.py +916 -0
  47. code_puppy/command_line/add_model_menu.py +1079 -0
  48. code_puppy/command_line/agent_menu.py +395 -0
  49. code_puppy/command_line/attachments.py +395 -0
  50. code_puppy/command_line/autosave_menu.py +605 -0
  51. code_puppy/command_line/clipboard.py +527 -0
  52. code_puppy/command_line/colors_menu.py +520 -0
  53. code_puppy/command_line/command_handler.py +233 -627
  54. code_puppy/command_line/command_registry.py +150 -0
  55. code_puppy/command_line/config_commands.py +715 -0
  56. code_puppy/command_line/core_commands.py +792 -0
  57. code_puppy/command_line/diff_menu.py +863 -0
  58. code_puppy/command_line/load_context_completion.py +15 -22
  59. code_puppy/command_line/mcp/base.py +1 -4
  60. code_puppy/command_line/mcp/catalog_server_installer.py +175 -0
  61. code_puppy/command_line/mcp/custom_server_form.py +688 -0
  62. code_puppy/command_line/mcp/custom_server_installer.py +195 -0
  63. code_puppy/command_line/mcp/edit_command.py +148 -0
  64. code_puppy/command_line/mcp/handler.py +9 -4
  65. code_puppy/command_line/mcp/help_command.py +6 -5
  66. code_puppy/command_line/mcp/install_command.py +16 -27
  67. code_puppy/command_line/mcp/install_menu.py +685 -0
  68. code_puppy/command_line/mcp/list_command.py +3 -3
  69. code_puppy/command_line/mcp/logs_command.py +174 -65
  70. code_puppy/command_line/mcp/remove_command.py +2 -2
  71. code_puppy/command_line/mcp/restart_command.py +12 -4
  72. code_puppy/command_line/mcp/search_command.py +17 -11
  73. code_puppy/command_line/mcp/start_all_command.py +22 -13
  74. code_puppy/command_line/mcp/start_command.py +50 -31
  75. code_puppy/command_line/mcp/status_command.py +6 -7
  76. code_puppy/command_line/mcp/stop_all_command.py +11 -8
  77. code_puppy/command_line/mcp/stop_command.py +11 -10
  78. code_puppy/command_line/mcp/test_command.py +2 -2
  79. code_puppy/command_line/mcp/utils.py +1 -1
  80. code_puppy/command_line/mcp/wizard_utils.py +22 -18
  81. code_puppy/command_line/mcp_completion.py +174 -0
  82. code_puppy/command_line/model_picker_completion.py +89 -30
  83. code_puppy/command_line/model_settings_menu.py +884 -0
  84. code_puppy/command_line/motd.py +14 -8
  85. code_puppy/command_line/onboarding_slides.py +179 -0
  86. code_puppy/command_line/onboarding_wizard.py +340 -0
  87. code_puppy/command_line/pin_command_completion.py +329 -0
  88. code_puppy/command_line/prompt_toolkit_completion.py +626 -75
  89. code_puppy/command_line/session_commands.py +296 -0
  90. code_puppy/command_line/utils.py +54 -0
  91. code_puppy/config.py +1181 -51
  92. code_puppy/error_logging.py +118 -0
  93. code_puppy/gemini_code_assist.py +385 -0
  94. code_puppy/gemini_model.py +602 -0
  95. code_puppy/http_utils.py +220 -104
  96. code_puppy/keymap.py +128 -0
  97. code_puppy/main.py +5 -594
  98. code_puppy/{mcp → mcp_}/__init__.py +17 -0
  99. code_puppy/{mcp → mcp_}/async_lifecycle.py +35 -4
  100. code_puppy/{mcp → mcp_}/blocking_startup.py +70 -43
  101. code_puppy/{mcp → mcp_}/captured_stdio_server.py +2 -2
  102. code_puppy/{mcp → mcp_}/config_wizard.py +5 -5
  103. code_puppy/{mcp → mcp_}/dashboard.py +15 -6
  104. code_puppy/{mcp → mcp_}/examples/retry_example.py +4 -1
  105. code_puppy/{mcp → mcp_}/managed_server.py +66 -39
  106. code_puppy/{mcp → mcp_}/manager.py +146 -52
  107. code_puppy/mcp_/mcp_logs.py +224 -0
  108. code_puppy/{mcp → mcp_}/registry.py +6 -6
  109. code_puppy/{mcp → mcp_}/server_registry_catalog.py +25 -8
  110. code_puppy/messaging/__init__.py +199 -2
  111. code_puppy/messaging/bus.py +610 -0
  112. code_puppy/messaging/commands.py +167 -0
  113. code_puppy/messaging/markdown_patches.py +57 -0
  114. code_puppy/messaging/message_queue.py +17 -48
  115. code_puppy/messaging/messages.py +500 -0
  116. code_puppy/messaging/queue_console.py +1 -24
  117. code_puppy/messaging/renderers.py +43 -146
  118. code_puppy/messaging/rich_renderer.py +1027 -0
  119. code_puppy/messaging/spinner/__init__.py +33 -5
  120. code_puppy/messaging/spinner/console_spinner.py +92 -52
  121. code_puppy/messaging/spinner/spinner_base.py +29 -0
  122. code_puppy/messaging/subagent_console.py +461 -0
  123. code_puppy/model_factory.py +686 -80
  124. code_puppy/model_utils.py +167 -0
  125. code_puppy/models.json +86 -104
  126. code_puppy/models_dev_api.json +1 -0
  127. code_puppy/models_dev_parser.py +592 -0
  128. code_puppy/plugins/__init__.py +164 -10
  129. code_puppy/plugins/antigravity_oauth/__init__.py +10 -0
  130. code_puppy/plugins/antigravity_oauth/accounts.py +406 -0
  131. code_puppy/plugins/antigravity_oauth/antigravity_model.py +704 -0
  132. code_puppy/plugins/antigravity_oauth/config.py +42 -0
  133. code_puppy/plugins/antigravity_oauth/constants.py +136 -0
  134. code_puppy/plugins/antigravity_oauth/oauth.py +478 -0
  135. code_puppy/plugins/antigravity_oauth/register_callbacks.py +406 -0
  136. code_puppy/plugins/antigravity_oauth/storage.py +271 -0
  137. code_puppy/plugins/antigravity_oauth/test_plugin.py +319 -0
  138. code_puppy/plugins/antigravity_oauth/token.py +167 -0
  139. code_puppy/plugins/antigravity_oauth/transport.py +767 -0
  140. code_puppy/plugins/antigravity_oauth/utils.py +169 -0
  141. code_puppy/plugins/chatgpt_oauth/__init__.py +8 -0
  142. code_puppy/plugins/chatgpt_oauth/config.py +52 -0
  143. code_puppy/plugins/chatgpt_oauth/oauth_flow.py +328 -0
  144. code_puppy/plugins/chatgpt_oauth/register_callbacks.py +94 -0
  145. code_puppy/plugins/chatgpt_oauth/test_plugin.py +293 -0
  146. code_puppy/plugins/chatgpt_oauth/utils.py +489 -0
  147. code_puppy/plugins/claude_code_oauth/README.md +167 -0
  148. code_puppy/plugins/claude_code_oauth/SETUP.md +93 -0
  149. code_puppy/plugins/claude_code_oauth/__init__.py +6 -0
  150. code_puppy/plugins/claude_code_oauth/config.py +50 -0
  151. code_puppy/plugins/claude_code_oauth/register_callbacks.py +308 -0
  152. code_puppy/plugins/claude_code_oauth/test_plugin.py +283 -0
  153. code_puppy/plugins/claude_code_oauth/utils.py +518 -0
  154. code_puppy/plugins/customizable_commands/__init__.py +0 -0
  155. code_puppy/plugins/customizable_commands/register_callbacks.py +169 -0
  156. code_puppy/plugins/example_custom_command/README.md +280 -0
  157. code_puppy/plugins/example_custom_command/register_callbacks.py +51 -0
  158. code_puppy/plugins/file_permission_handler/__init__.py +4 -0
  159. code_puppy/plugins/file_permission_handler/register_callbacks.py +523 -0
  160. code_puppy/plugins/frontend_emitter/__init__.py +25 -0
  161. code_puppy/plugins/frontend_emitter/emitter.py +121 -0
  162. code_puppy/plugins/frontend_emitter/register_callbacks.py +261 -0
  163. code_puppy/plugins/oauth_puppy_html.py +228 -0
  164. code_puppy/plugins/shell_safety/__init__.py +6 -0
  165. code_puppy/plugins/shell_safety/agent_shell_safety.py +69 -0
  166. code_puppy/plugins/shell_safety/command_cache.py +156 -0
  167. code_puppy/plugins/shell_safety/register_callbacks.py +202 -0
  168. code_puppy/prompts/antigravity_system_prompt.md +1 -0
  169. code_puppy/prompts/codex_system_prompt.md +310 -0
  170. code_puppy/pydantic_patches.py +131 -0
  171. code_puppy/reopenable_async_client.py +8 -8
  172. code_puppy/round_robin_model.py +10 -15
  173. code_puppy/session_storage.py +294 -0
  174. code_puppy/status_display.py +21 -4
  175. code_puppy/summarization_agent.py +52 -14
  176. code_puppy/terminal_utils.py +418 -0
  177. code_puppy/tools/__init__.py +139 -6
  178. code_puppy/tools/agent_tools.py +548 -49
  179. code_puppy/tools/browser/__init__.py +37 -0
  180. code_puppy/tools/browser/browser_control.py +289 -0
  181. code_puppy/tools/browser/browser_interactions.py +545 -0
  182. code_puppy/tools/browser/browser_locators.py +640 -0
  183. code_puppy/tools/browser/browser_manager.py +316 -0
  184. code_puppy/tools/browser/browser_navigation.py +251 -0
  185. code_puppy/tools/browser/browser_screenshot.py +179 -0
  186. code_puppy/tools/browser/browser_scripts.py +462 -0
  187. code_puppy/tools/browser/browser_workflows.py +221 -0
  188. code_puppy/tools/browser/chromium_terminal_manager.py +259 -0
  189. code_puppy/tools/browser/terminal_command_tools.py +521 -0
  190. code_puppy/tools/browser/terminal_screenshot_tools.py +556 -0
  191. code_puppy/tools/browser/terminal_tools.py +525 -0
  192. code_puppy/tools/command_runner.py +941 -153
  193. code_puppy/tools/common.py +1146 -6
  194. code_puppy/tools/display.py +84 -0
  195. code_puppy/tools/file_modifications.py +288 -89
  196. code_puppy/tools/file_operations.py +352 -266
  197. code_puppy/tools/subagent_context.py +158 -0
  198. code_puppy/uvx_detection.py +242 -0
  199. code_puppy/version_checker.py +30 -11
  200. code_puppy-0.0.366.data/data/code_puppy/models.json +110 -0
  201. code_puppy-0.0.366.data/data/code_puppy/models_dev_api.json +1 -0
  202. {code_puppy-0.0.169.dist-info → code_puppy-0.0.366.dist-info}/METADATA +184 -67
  203. code_puppy-0.0.366.dist-info/RECORD +217 -0
  204. {code_puppy-0.0.169.dist-info → code_puppy-0.0.366.dist-info}/WHEEL +1 -1
  205. {code_puppy-0.0.169.dist-info → code_puppy-0.0.366.dist-info}/entry_points.txt +1 -0
  206. code_puppy/agent.py +0 -231
  207. code_puppy/agents/agent_orchestrator.json +0 -26
  208. code_puppy/agents/runtime_manager.py +0 -272
  209. code_puppy/command_line/mcp/add_command.py +0 -183
  210. code_puppy/command_line/meta_command_handler.py +0 -153
  211. code_puppy/message_history_processor.py +0 -490
  212. code_puppy/messaging/spinner/textual_spinner.py +0 -101
  213. code_puppy/state_management.py +0 -200
  214. code_puppy/tui/__init__.py +0 -10
  215. code_puppy/tui/app.py +0 -986
  216. code_puppy/tui/components/__init__.py +0 -21
  217. code_puppy/tui/components/chat_view.py +0 -550
  218. code_puppy/tui/components/command_history_modal.py +0 -218
  219. code_puppy/tui/components/copy_button.py +0 -139
  220. code_puppy/tui/components/custom_widgets.py +0 -63
  221. code_puppy/tui/components/human_input_modal.py +0 -175
  222. code_puppy/tui/components/input_area.py +0 -167
  223. code_puppy/tui/components/sidebar.py +0 -309
  224. code_puppy/tui/components/status_bar.py +0 -182
  225. code_puppy/tui/messages.py +0 -27
  226. code_puppy/tui/models/__init__.py +0 -8
  227. code_puppy/tui/models/chat_message.py +0 -25
  228. code_puppy/tui/models/command_history.py +0 -89
  229. code_puppy/tui/models/enums.py +0 -24
  230. code_puppy/tui/screens/__init__.py +0 -15
  231. code_puppy/tui/screens/help.py +0 -130
  232. code_puppy/tui/screens/mcp_install_wizard.py +0 -803
  233. code_puppy/tui/screens/settings.py +0 -290
  234. code_puppy/tui/screens/tools.py +0 -74
  235. code_puppy-0.0.169.data/data/code_puppy/models.json +0 -128
  236. code_puppy-0.0.169.dist-info/RECORD +0 -112
  237. /code_puppy/{mcp → mcp_}/circuit_breaker.py +0 -0
  238. /code_puppy/{mcp → mcp_}/error_isolation.py +0 -0
  239. /code_puppy/{mcp → mcp_}/health_monitor.py +0 -0
  240. /code_puppy/{mcp → mcp_}/retry_manager.py +0 -0
  241. /code_puppy/{mcp → mcp_}/status_tracker.py +0 -0
  242. /code_puppy/{mcp → mcp_}/system_tools.py +0 -0
  243. {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 both TUI and interactive modes to consume the same messages
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
- # Check if we're in TUI mode - if so, try to yield control to the event loop
222
- from code_puppy.state_management import is_tui_mode
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 received for prompt {prompt_id} within {timeout} seconds"
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 = "[dim]" + "─" * 100 + "\n" + "[/dim]", **metadata):
325
+ def emit_divider(content: str = "─" * 100 + "\n", **metadata):
339
326
  """Emit a divider line"""
340
- from code_puppy.state_management import is_tui_mode
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
- # In interactive mode, use direct input instead of the queue system
353
- if not is_tui_mode():
354
- # Emit the prompt as a message for display
355
- from code_puppy.messaging import emit_info
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
- emit_info(f"[yellow]{prompt_text}[/yellow]")
340
+ emit_info(prompt_text)
358
341
 
359
- # Get input directly
360
- try:
361
- # Try to use rich console for better formatting
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):