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.
Files changed (231) hide show
  1. code_puppy/__init__.py +7 -1
  2. code_puppy/agents/__init__.py +2 -0
  3. code_puppy/agents/agent_c_reviewer.py +59 -6
  4. code_puppy/agents/agent_code_puppy.py +7 -1
  5. code_puppy/agents/agent_code_reviewer.py +12 -2
  6. code_puppy/agents/agent_cpp_reviewer.py +73 -6
  7. code_puppy/agents/agent_creator_agent.py +45 -4
  8. code_puppy/agents/agent_golang_reviewer.py +92 -3
  9. code_puppy/agents/agent_javascript_reviewer.py +101 -8
  10. code_puppy/agents/agent_manager.py +81 -4
  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 +28 -6
  15. code_puppy/agents/agent_qa_expert.py +98 -6
  16. code_puppy/agents/agent_qa_kitten.py +12 -7
  17. code_puppy/agents/agent_security_auditor.py +113 -3
  18. code_puppy/agents/agent_terminal_qa.py +323 -0
  19. code_puppy/agents/agent_typescript_reviewer.py +106 -7
  20. code_puppy/agents/base_agent.py +802 -176
  21. code_puppy/agents/event_stream_handler.py +350 -0
  22. code_puppy/agents/pack/__init__.py +34 -0
  23. code_puppy/agents/pack/bloodhound.py +304 -0
  24. code_puppy/agents/pack/husky.py +321 -0
  25. code_puppy/agents/pack/retriever.py +393 -0
  26. code_puppy/agents/pack/shepherd.py +348 -0
  27. code_puppy/agents/pack/terrier.py +287 -0
  28. code_puppy/agents/pack/watchdog.py +367 -0
  29. code_puppy/agents/prompt_reviewer.py +145 -0
  30. code_puppy/agents/subagent_stream_handler.py +276 -0
  31. code_puppy/api/__init__.py +13 -0
  32. code_puppy/api/app.py +169 -0
  33. code_puppy/api/main.py +21 -0
  34. code_puppy/api/pty_manager.py +446 -0
  35. code_puppy/api/routers/__init__.py +12 -0
  36. code_puppy/api/routers/agents.py +36 -0
  37. code_puppy/api/routers/commands.py +217 -0
  38. code_puppy/api/routers/config.py +74 -0
  39. code_puppy/api/routers/sessions.py +232 -0
  40. code_puppy/api/templates/terminal.html +361 -0
  41. code_puppy/api/websocket.py +154 -0
  42. code_puppy/callbacks.py +142 -4
  43. code_puppy/chatgpt_codex_client.py +283 -0
  44. code_puppy/claude_cache_client.py +586 -0
  45. code_puppy/cli_runner.py +916 -0
  46. code_puppy/command_line/add_model_menu.py +1079 -0
  47. code_puppy/command_line/agent_menu.py +395 -0
  48. code_puppy/command_line/attachments.py +10 -5
  49. code_puppy/command_line/autosave_menu.py +605 -0
  50. code_puppy/command_line/clipboard.py +527 -0
  51. code_puppy/command_line/colors_menu.py +520 -0
  52. code_puppy/command_line/command_handler.py +176 -738
  53. code_puppy/command_line/command_registry.py +150 -0
  54. code_puppy/command_line/config_commands.py +715 -0
  55. code_puppy/command_line/core_commands.py +792 -0
  56. code_puppy/command_line/diff_menu.py +863 -0
  57. code_puppy/command_line/load_context_completion.py +15 -22
  58. code_puppy/command_line/mcp/base.py +0 -3
  59. code_puppy/command_line/mcp/catalog_server_installer.py +175 -0
  60. code_puppy/command_line/mcp/custom_server_form.py +688 -0
  61. code_puppy/command_line/mcp/custom_server_installer.py +195 -0
  62. code_puppy/command_line/mcp/edit_command.py +148 -0
  63. code_puppy/command_line/mcp/handler.py +9 -4
  64. code_puppy/command_line/mcp/help_command.py +6 -5
  65. code_puppy/command_line/mcp/install_command.py +15 -26
  66. code_puppy/command_line/mcp/install_menu.py +685 -0
  67. code_puppy/command_line/mcp/list_command.py +2 -2
  68. code_puppy/command_line/mcp/logs_command.py +174 -65
  69. code_puppy/command_line/mcp/remove_command.py +2 -2
  70. code_puppy/command_line/mcp/restart_command.py +12 -4
  71. code_puppy/command_line/mcp/search_command.py +16 -10
  72. code_puppy/command_line/mcp/start_all_command.py +18 -6
  73. code_puppy/command_line/mcp/start_command.py +47 -25
  74. code_puppy/command_line/mcp/status_command.py +4 -5
  75. code_puppy/command_line/mcp/stop_all_command.py +7 -1
  76. code_puppy/command_line/mcp/stop_command.py +8 -4
  77. code_puppy/command_line/mcp/test_command.py +2 -2
  78. code_puppy/command_line/mcp/wizard_utils.py +20 -16
  79. code_puppy/command_line/mcp_completion.py +174 -0
  80. code_puppy/command_line/model_picker_completion.py +75 -25
  81. code_puppy/command_line/model_settings_menu.py +884 -0
  82. code_puppy/command_line/motd.py +14 -8
  83. code_puppy/command_line/onboarding_slides.py +179 -0
  84. code_puppy/command_line/onboarding_wizard.py +340 -0
  85. code_puppy/command_line/pin_command_completion.py +329 -0
  86. code_puppy/command_line/prompt_toolkit_completion.py +463 -63
  87. code_puppy/command_line/session_commands.py +296 -0
  88. code_puppy/command_line/utils.py +54 -0
  89. code_puppy/config.py +898 -112
  90. code_puppy/error_logging.py +118 -0
  91. code_puppy/gemini_code_assist.py +385 -0
  92. code_puppy/gemini_model.py +602 -0
  93. code_puppy/http_utils.py +210 -148
  94. code_puppy/keymap.py +128 -0
  95. code_puppy/main.py +5 -698
  96. code_puppy/mcp_/__init__.py +17 -0
  97. code_puppy/mcp_/async_lifecycle.py +35 -4
  98. code_puppy/mcp_/blocking_startup.py +70 -43
  99. code_puppy/mcp_/captured_stdio_server.py +2 -2
  100. code_puppy/mcp_/config_wizard.py +4 -4
  101. code_puppy/mcp_/dashboard.py +15 -6
  102. code_puppy/mcp_/managed_server.py +65 -38
  103. code_puppy/mcp_/manager.py +146 -52
  104. code_puppy/mcp_/mcp_logs.py +224 -0
  105. code_puppy/mcp_/registry.py +6 -6
  106. code_puppy/mcp_/server_registry_catalog.py +24 -5
  107. code_puppy/messaging/__init__.py +199 -2
  108. code_puppy/messaging/bus.py +610 -0
  109. code_puppy/messaging/commands.py +167 -0
  110. code_puppy/messaging/markdown_patches.py +57 -0
  111. code_puppy/messaging/message_queue.py +17 -48
  112. code_puppy/messaging/messages.py +500 -0
  113. code_puppy/messaging/queue_console.py +1 -24
  114. code_puppy/messaging/renderers.py +43 -146
  115. code_puppy/messaging/rich_renderer.py +1027 -0
  116. code_puppy/messaging/spinner/__init__.py +21 -5
  117. code_puppy/messaging/spinner/console_spinner.py +86 -51
  118. code_puppy/messaging/subagent_console.py +461 -0
  119. code_puppy/model_factory.py +634 -83
  120. code_puppy/model_utils.py +167 -0
  121. code_puppy/models.json +66 -68
  122. code_puppy/models_dev_api.json +1 -0
  123. code_puppy/models_dev_parser.py +592 -0
  124. code_puppy/plugins/__init__.py +164 -10
  125. code_puppy/plugins/antigravity_oauth/__init__.py +10 -0
  126. code_puppy/plugins/antigravity_oauth/accounts.py +406 -0
  127. code_puppy/plugins/antigravity_oauth/antigravity_model.py +704 -0
  128. code_puppy/plugins/antigravity_oauth/config.py +42 -0
  129. code_puppy/plugins/antigravity_oauth/constants.py +136 -0
  130. code_puppy/plugins/antigravity_oauth/oauth.py +478 -0
  131. code_puppy/plugins/antigravity_oauth/register_callbacks.py +406 -0
  132. code_puppy/plugins/antigravity_oauth/storage.py +271 -0
  133. code_puppy/plugins/antigravity_oauth/test_plugin.py +319 -0
  134. code_puppy/plugins/antigravity_oauth/token.py +167 -0
  135. code_puppy/plugins/antigravity_oauth/transport.py +767 -0
  136. code_puppy/plugins/antigravity_oauth/utils.py +169 -0
  137. code_puppy/plugins/chatgpt_oauth/__init__.py +8 -0
  138. code_puppy/plugins/chatgpt_oauth/config.py +52 -0
  139. code_puppy/plugins/chatgpt_oauth/oauth_flow.py +328 -0
  140. code_puppy/plugins/chatgpt_oauth/register_callbacks.py +94 -0
  141. code_puppy/plugins/chatgpt_oauth/test_plugin.py +293 -0
  142. code_puppy/plugins/chatgpt_oauth/utils.py +489 -0
  143. code_puppy/plugins/claude_code_oauth/README.md +167 -0
  144. code_puppy/plugins/claude_code_oauth/SETUP.md +93 -0
  145. code_puppy/plugins/claude_code_oauth/__init__.py +6 -0
  146. code_puppy/plugins/claude_code_oauth/config.py +50 -0
  147. code_puppy/plugins/claude_code_oauth/register_callbacks.py +308 -0
  148. code_puppy/plugins/claude_code_oauth/test_plugin.py +283 -0
  149. code_puppy/plugins/claude_code_oauth/utils.py +518 -0
  150. code_puppy/plugins/customizable_commands/__init__.py +0 -0
  151. code_puppy/plugins/customizable_commands/register_callbacks.py +169 -0
  152. code_puppy/plugins/example_custom_command/README.md +280 -0
  153. code_puppy/plugins/example_custom_command/register_callbacks.py +2 -2
  154. code_puppy/plugins/file_permission_handler/__init__.py +4 -0
  155. code_puppy/plugins/file_permission_handler/register_callbacks.py +523 -0
  156. code_puppy/plugins/frontend_emitter/__init__.py +25 -0
  157. code_puppy/plugins/frontend_emitter/emitter.py +121 -0
  158. code_puppy/plugins/frontend_emitter/register_callbacks.py +261 -0
  159. code_puppy/plugins/oauth_puppy_html.py +228 -0
  160. code_puppy/plugins/shell_safety/__init__.py +6 -0
  161. code_puppy/plugins/shell_safety/agent_shell_safety.py +69 -0
  162. code_puppy/plugins/shell_safety/command_cache.py +156 -0
  163. code_puppy/plugins/shell_safety/register_callbacks.py +202 -0
  164. code_puppy/prompts/antigravity_system_prompt.md +1 -0
  165. code_puppy/prompts/codex_system_prompt.md +310 -0
  166. code_puppy/pydantic_patches.py +131 -0
  167. code_puppy/reopenable_async_client.py +8 -8
  168. code_puppy/round_robin_model.py +9 -12
  169. code_puppy/session_storage.py +2 -1
  170. code_puppy/status_display.py +21 -4
  171. code_puppy/summarization_agent.py +41 -13
  172. code_puppy/terminal_utils.py +418 -0
  173. code_puppy/tools/__init__.py +37 -1
  174. code_puppy/tools/agent_tools.py +536 -52
  175. code_puppy/tools/browser/__init__.py +37 -0
  176. code_puppy/tools/browser/browser_control.py +19 -23
  177. code_puppy/tools/browser/browser_interactions.py +41 -48
  178. code_puppy/tools/browser/browser_locators.py +36 -38
  179. code_puppy/tools/browser/browser_manager.py +316 -0
  180. code_puppy/tools/browser/browser_navigation.py +16 -16
  181. code_puppy/tools/browser/browser_screenshot.py +79 -143
  182. code_puppy/tools/browser/browser_scripts.py +32 -42
  183. code_puppy/tools/browser/browser_workflows.py +44 -27
  184. code_puppy/tools/browser/chromium_terminal_manager.py +259 -0
  185. code_puppy/tools/browser/terminal_command_tools.py +521 -0
  186. code_puppy/tools/browser/terminal_screenshot_tools.py +556 -0
  187. code_puppy/tools/browser/terminal_tools.py +525 -0
  188. code_puppy/tools/command_runner.py +930 -147
  189. code_puppy/tools/common.py +1113 -5
  190. code_puppy/tools/display.py +84 -0
  191. code_puppy/tools/file_modifications.py +288 -89
  192. code_puppy/tools/file_operations.py +226 -154
  193. code_puppy/tools/subagent_context.py +158 -0
  194. code_puppy/uvx_detection.py +242 -0
  195. code_puppy/version_checker.py +30 -11
  196. code_puppy-0.0.366.data/data/code_puppy/models.json +110 -0
  197. code_puppy-0.0.366.data/data/code_puppy/models_dev_api.json +1 -0
  198. {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/METADATA +149 -75
  199. code_puppy-0.0.366.dist-info/RECORD +217 -0
  200. {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/WHEEL +1 -1
  201. code_puppy/command_line/mcp/add_command.py +0 -183
  202. code_puppy/messaging/spinner/textual_spinner.py +0 -106
  203. code_puppy/tools/browser/camoufox_manager.py +0 -216
  204. code_puppy/tools/browser/vqa_agent.py +0 -70
  205. code_puppy/tui/__init__.py +0 -10
  206. code_puppy/tui/app.py +0 -1105
  207. code_puppy/tui/components/__init__.py +0 -21
  208. code_puppy/tui/components/chat_view.py +0 -551
  209. code_puppy/tui/components/command_history_modal.py +0 -218
  210. code_puppy/tui/components/copy_button.py +0 -139
  211. code_puppy/tui/components/custom_widgets.py +0 -63
  212. code_puppy/tui/components/human_input_modal.py +0 -175
  213. code_puppy/tui/components/input_area.py +0 -167
  214. code_puppy/tui/components/sidebar.py +0 -309
  215. code_puppy/tui/components/status_bar.py +0 -185
  216. code_puppy/tui/messages.py +0 -27
  217. code_puppy/tui/models/__init__.py +0 -8
  218. code_puppy/tui/models/chat_message.py +0 -25
  219. code_puppy/tui/models/command_history.py +0 -89
  220. code_puppy/tui/models/enums.py +0 -24
  221. code_puppy/tui/screens/__init__.py +0 -17
  222. code_puppy/tui/screens/autosave_picker.py +0 -175
  223. code_puppy/tui/screens/help.py +0 -130
  224. code_puppy/tui/screens/mcp_install_wizard.py +0 -803
  225. code_puppy/tui/screens/settings.py +0 -306
  226. code_puppy/tui/screens/tools.py +0 -74
  227. code_puppy/tui_state.py +0 -55
  228. code_puppy-0.0.214.data/data/code_puppy/models.json +0 -112
  229. code_puppy-0.0.214.dist-info/RECORD +0 -131
  230. {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/entry_points.txt +0 -0
  231. {code_puppy-0.0.214.dist-info → code_puppy-0.0.366.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env python3
2
+ """Manual sanity checks for the Claude Code OAuth plugin."""
3
+
4
+ import os
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ # Ensure project root on path
9
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent
10
+ sys.path.insert(0, str(PROJECT_ROOT))
11
+
12
+ # Switch to project root for predictable relative paths
13
+ os.chdir(PROJECT_ROOT)
14
+
15
+
16
+ def test_plugin_imports() -> bool:
17
+ """Verify the plugin modules import correctly."""
18
+ print("\n=== Testing Plugin Imports ===")
19
+
20
+ try:
21
+ from code_puppy.plugins.claude_code_oauth.config import (
22
+ CLAUDE_CODE_OAUTH_CONFIG,
23
+ get_token_storage_path,
24
+ )
25
+
26
+ print("✅ Config import successful")
27
+ print(f"✅ Token storage path: {get_token_storage_path()}")
28
+ print(f"✅ Known auth URL: {CLAUDE_CODE_OAUTH_CONFIG['auth_url']}")
29
+ except Exception as exc: # pragma: no cover - manual harness
30
+ print(f"❌ Config import failed: {exc}")
31
+ return False
32
+
33
+ try:
34
+ from code_puppy.plugins.claude_code_oauth.utils import (
35
+ add_models_to_extra_config,
36
+ build_authorization_url,
37
+ exchange_code_for_tokens,
38
+ fetch_claude_code_models,
39
+ load_claude_models,
40
+ load_stored_tokens,
41
+ parse_authorization_code,
42
+ prepare_oauth_context,
43
+ remove_claude_code_models,
44
+ save_claude_models,
45
+ save_tokens,
46
+ )
47
+
48
+ _ = (
49
+ add_models_to_extra_config,
50
+ build_authorization_url,
51
+ exchange_code_for_tokens,
52
+ fetch_claude_code_models,
53
+ load_claude_models,
54
+ load_stored_tokens,
55
+ parse_authorization_code,
56
+ prepare_oauth_context,
57
+ remove_claude_code_models,
58
+ save_claude_models,
59
+ save_tokens,
60
+ )
61
+ print("✅ Utils import successful")
62
+ except Exception as exc: # pragma: no cover - manual harness
63
+ print(f"❌ Utils import failed: {exc}")
64
+ return False
65
+
66
+ try:
67
+ from code_puppy.plugins.claude_code_oauth.register_callbacks import (
68
+ _custom_help,
69
+ _handle_custom_command,
70
+ )
71
+
72
+ commands = _custom_help()
73
+ print("✅ Callback registration import successful")
74
+ for name, description in commands:
75
+ print(f" /{name} - {description}")
76
+ # Ensure handler callable exists
77
+ _ = _handle_custom_command
78
+ except Exception as exc: # pragma: no cover - manual harness
79
+ print(f"❌ Callback import failed: {exc}")
80
+ return False
81
+
82
+ return True
83
+
84
+
85
+ def test_oauth_helpers() -> bool:
86
+ """Exercise helper functions without performing network requests."""
87
+ print("\n=== Testing OAuth Helper Functions ===")
88
+
89
+ try:
90
+ from urllib.parse import parse_qs, urlparse
91
+
92
+ from code_puppy.plugins.claude_code_oauth.utils import (
93
+ assign_redirect_uri,
94
+ build_authorization_url,
95
+ parse_authorization_code,
96
+ prepare_oauth_context,
97
+ )
98
+
99
+ context = prepare_oauth_context()
100
+ assert context.state, "Expected non-empty OAuth state"
101
+ assert context.code_verifier, "Expected PKCE code verifier"
102
+ assert context.code_challenge, "Expected PKCE code challenge"
103
+
104
+ assign_redirect_uri(context, 8765)
105
+ auth_url = build_authorization_url(context)
106
+ parsed = urlparse(auth_url)
107
+ params = parse_qs(parsed.query)
108
+ print(f"✅ Authorization URL: {auth_url}")
109
+ assert parsed.scheme == "https", "Authorization URL must use https"
110
+ assert params.get("client_id", [None])[0], "client_id missing"
111
+ assert params.get("code_challenge_method", [None])[0] == "S256"
112
+ assert params.get("state", [None])[0] == context.state
113
+ assert params.get("code_challenge", [None])[0] == context.code_challenge
114
+
115
+ sample_code = f"MYCODE#{context.state}"
116
+ parsed_code, parsed_state = parse_authorization_code(sample_code)
117
+ assert parsed_code == "MYCODE", "Code parsing failed"
118
+ assert parsed_state == context.state, "State parsing failed"
119
+ print("✅ parse_authorization_code handled state suffix correctly")
120
+
121
+ parsed_code, parsed_state = parse_authorization_code("SINGLECODE")
122
+ assert parsed_code == "SINGLECODE" and parsed_state is None
123
+ print("✅ parse_authorization_code handled bare code correctly")
124
+
125
+ return True
126
+
127
+ except AssertionError as exc:
128
+ print(f"❌ Assertion failed: {exc}")
129
+ return False
130
+ except Exception as exc: # pragma: no cover - manual harness
131
+ print(f"❌ OAuth helper test crashed: {exc}")
132
+ import traceback
133
+
134
+ traceback.print_exc()
135
+ return False
136
+
137
+
138
+ def test_file_operations() -> bool:
139
+ """Ensure token/model storage helpers behave sanely."""
140
+ print("\n=== Testing File Operations ===")
141
+
142
+ try:
143
+ from code_puppy.plugins.claude_code_oauth.config import (
144
+ get_claude_models_path,
145
+ get_token_storage_path,
146
+ )
147
+ from code_puppy.plugins.claude_code_oauth.utils import (
148
+ load_claude_models,
149
+ load_stored_tokens,
150
+ )
151
+
152
+ tokens = load_stored_tokens()
153
+ print(f"✅ Token load result: {'present' if tokens else 'none'}")
154
+
155
+ models = load_claude_models()
156
+ print(f"✅ Loaded {len(models)} Claude models")
157
+ for name, config in models.items():
158
+ print(f" - {name}: {config.get('type', 'unknown type')}")
159
+
160
+ token_path = get_token_storage_path()
161
+ models_path = get_claude_models_path()
162
+ token_path.parent.mkdir(parents=True, exist_ok=True)
163
+ models_path.parent.mkdir(parents=True, exist_ok=True)
164
+ print(f"✅ Token path: {token_path}")
165
+ print(f"✅ Models path: {models_path}")
166
+
167
+ return True
168
+
169
+ except Exception as exc: # pragma: no cover - manual harness
170
+ print(f"❌ File operations test failed: {exc}")
171
+ import traceback
172
+
173
+ traceback.print_exc()
174
+ return False
175
+
176
+
177
+ def test_command_handlers() -> bool:
178
+ """Smoke-test command handler routing without simulating authentication."""
179
+ print("\n=== Testing Command Handlers ===")
180
+
181
+ from code_puppy.plugins.claude_code_oauth.register_callbacks import (
182
+ _handle_custom_command,
183
+ )
184
+
185
+ unknown = _handle_custom_command("/bogus", "bogus")
186
+ print(f"✅ Unknown command returned: {unknown}")
187
+
188
+ partial = _handle_custom_command("/claude-code", "claude-code")
189
+ print(f"✅ Partial command returned: {partial}")
190
+
191
+ # Do not invoke the real auth command here because it prompts for input.
192
+ return True
193
+
194
+
195
+ def test_configuration() -> bool:
196
+ """Validate configuration keys and basic formats."""
197
+ print("\n=== Testing Configuration ===")
198
+
199
+ try:
200
+ from code_puppy.plugins.claude_code_oauth.config import CLAUDE_CODE_OAUTH_CONFIG
201
+
202
+ required_keys = [
203
+ "auth_url",
204
+ "token_url",
205
+ "api_base_url",
206
+ "client_id",
207
+ "scope",
208
+ "redirect_host",
209
+ "redirect_path",
210
+ "callback_port_range",
211
+ "callback_timeout",
212
+ "token_storage",
213
+ "prefix",
214
+ "default_context_length",
215
+ "api_key_env_var",
216
+ ]
217
+
218
+ missing = [key for key in required_keys if key not in CLAUDE_CODE_OAUTH_CONFIG]
219
+ if missing:
220
+ print(f"❌ Missing configuration keys: {missing}")
221
+ return False
222
+
223
+ for key in required_keys:
224
+ value = CLAUDE_CODE_OAUTH_CONFIG[key]
225
+ print(f"✅ {key}: {value}")
226
+
227
+ for url_key in ["auth_url", "token_url", "api_base_url"]:
228
+ url = CLAUDE_CODE_OAUTH_CONFIG[url_key]
229
+ if not str(url).startswith("https://"):
230
+ print(f"❌ URL must use HTTPS: {url_key} -> {url}")
231
+ return False
232
+ print(f"✅ {url_key} uses HTTPS")
233
+
234
+ return True
235
+
236
+ except Exception as exc: # pragma: no cover - manual harness
237
+ print(f"❌ Configuration test crashed: {exc}")
238
+ import traceback
239
+
240
+ traceback.print_exc()
241
+ return False
242
+
243
+
244
+ def main() -> bool:
245
+ """Run all manual checks."""
246
+ print("Claude Code OAuth Plugin Test Suite")
247
+ print("=" * 40)
248
+
249
+ tests = [
250
+ test_plugin_imports,
251
+ test_oauth_helpers,
252
+ test_file_operations,
253
+ test_command_handlers,
254
+ test_configuration,
255
+ ]
256
+
257
+ passed = 0
258
+ for test in tests:
259
+ try:
260
+ if test():
261
+ passed += 1
262
+ else:
263
+ print("\n❌ Test failed")
264
+ except Exception as exc: # pragma: no cover - manual harness
265
+ print(f"\n❌ Test crashed: {exc}")
266
+
267
+ print("\n=== Test Results ===")
268
+ print(f"Passed: {passed}/{len(tests)}")
269
+
270
+ if passed == len(tests):
271
+ print("✅ All sanity checks passed!")
272
+ print("Next steps:")
273
+ print("1. Restart Code Puppy if it was running")
274
+ print("2. Run /claude-code-auth")
275
+ print("3. Paste the Claude Console authorization code when prompted")
276
+ return True
277
+
278
+ print("❌ Some checks failed. Investigate before using the plugin.")
279
+ return False
280
+
281
+
282
+ if __name__ == "__main__":
283
+ sys.exit(0 if main() else 1)