code-puppy 0.0.332__py3-none-any.whl → 0.0.334__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.
@@ -0,0 +1,416 @@
1
+ """Slide content for the onboarding wizard.
2
+
3
+ 🐶 Contains all slide definitions and content generators for the onboarding
4
+ wizard. Separated from the main wizard logic for maintainability.
5
+ """
6
+
7
+ from typing import List, Tuple
8
+
9
+ # ============================================================================
10
+ # Slide Data Constants
11
+ # ============================================================================
12
+
13
+ # Model subscription options for slide 1
14
+ MODEL_OPTIONS: List[Tuple[str, str, str]] = [
15
+ ("chatgpt", "ChatGPT Plus (Pro/Max)", "OAuth login with your ChatGPT subscription"),
16
+ ("claude", "Claude Code Pro/Max", "OAuth login with your Claude subscription"),
17
+ ("api_keys", "API Keys (OpenAI, Anthropic, etc.)", "Use your own API keys"),
18
+ ("openrouter", "OpenRouter", "Single API key for multiple providers"),
19
+ ("free", "Free tiers / Other providers", "Explore free and community models"),
20
+ ("skip", "Skip this", "Configure later with /set or /add_model"),
21
+ ]
22
+
23
+ # Common API keys users might want to configure
24
+ API_KEYS_INFO: List[Tuple[str, str]] = [
25
+ ("OPENAI_API_KEY", "OpenAI (GPT-5.2, GPT-5.2-codex)"),
26
+ ("ANTHROPIC_API_KEY", "Anthropic (Opus/Sonnet/Haiku 4.5)"),
27
+ ("GOOGLE_API_KEY", "Google (Gemini 3 Pro)"),
28
+ ("XAI_API_KEY", "xAI (Grok 4)"),
29
+ ("MINIMAX_API_KEY", "MiniMax (MiniMax M2.1)"),
30
+ ("OPENROUTER_API_KEY", "OpenRouter (100+ models)"),
31
+ ]
32
+
33
+ # Key agents to highlight
34
+ KEY_AGENTS: List[Tuple[str, str, str]] = [
35
+ ("planning-agent", "📋 Planning Agent", "Breaks down complex tasks"),
36
+ ("qa-kitten", "🐱 QA Kitten", "Browser automation with Playwright"),
37
+ ("security-auditor", "🛡️ Security Auditor", "Risk-based security review"),
38
+ ("code-reviewer", "🔍 Code Reviewer", "Holistic code review"),
39
+ ("python-programmer", "🐍 Python Programmer", "Modern Python specialist"),
40
+ ]
41
+
42
+
43
+ # ============================================================================
44
+ # Gradient Banner Generator
45
+ # ============================================================================
46
+
47
+
48
+ def get_gradient_banner() -> str:
49
+ """Generate the gradient CODE PUPPY banner.
50
+
51
+ Returns:
52
+ Rich markup string with gradient-colored pyfiglet banner.
53
+ """
54
+ try:
55
+ import pyfiglet
56
+
57
+ intro_lines = pyfiglet.figlet_format("CODE PUPPY", font="ansi_shadow").split(
58
+ "\n"
59
+ )
60
+
61
+ # Blue to cyan to green gradient (top to bottom)
62
+ gradient_colors = ["bright_blue", "bright_cyan", "bright_green"]
63
+
64
+ result_lines = []
65
+ for line_num, line in enumerate(intro_lines):
66
+ if line.strip():
67
+ color_idx = min(line_num // 2, len(gradient_colors) - 1)
68
+ color = gradient_colors[color_idx]
69
+ result_lines.append(f"[{color}]{line}[/{color}]")
70
+ else:
71
+ result_lines.append("")
72
+
73
+ return "\n".join(result_lines)
74
+ except ImportError:
75
+ # Fallback if pyfiglet not available
76
+ return (
77
+ "[bold bright_cyan]╔═══════════════════════════════╗\n"
78
+ "║ CODE PUPPY 🐶 ║\n"
79
+ "╚═══════════════════════════════╝[/bold bright_cyan]"
80
+ )
81
+
82
+
83
+ # ============================================================================
84
+ # Slide Content Generators
85
+ # ============================================================================
86
+
87
+
88
+ def slide_welcome() -> str:
89
+ """Slide 0: Welcome with gradient banner.
90
+
91
+ Returns:
92
+ Rich markup string for the slide content.
93
+ """
94
+ content = get_gradient_banner()
95
+ content += "\n\n"
96
+ content += "[bold white]Welcome to Code Puppy! 🐶[/bold white]\n\n"
97
+ content += "[dim]Let's get you set up for coding success![/dim]\n\n"
98
+ content += "[cyan]This wizard will help you configure:[/cyan]\n"
99
+ content += " • Model subscriptions & API keys\n"
100
+ content += " • MCP server integrations\n"
101
+ content += " • Appearance customization\n"
102
+ content += " • Agent system overview\n\n"
103
+ content += "[bold yellow]🎯 Navigation:[/bold yellow]\n"
104
+ content += "[green]→[/green] or [green]l[/green] Next slide\n"
105
+ content += "[green]←[/green] or [green]h[/green] Previous slide\n"
106
+ content += "[green]↓[/green] or [green]j[/green] Next option\n"
107
+ content += "[green]↑[/green] or [green]k[/green] Previous option\n"
108
+ content += "[green]Enter[/green] Select/proceed\n"
109
+ content += "[green]ESC[/green] Skip wizard\n\n"
110
+ content += "[dim]You can always run[/dim]\n"
111
+ content += "[cyan]/onboarding[/cyan] [dim]later![/dim]"
112
+
113
+ return content
114
+
115
+
116
+ def slide_model_subscription(
117
+ selected_option: int, options: List[Tuple[str, str]]
118
+ ) -> str:
119
+ """Slide 1: Model subscription selection.
120
+
121
+ Args:
122
+ selected_option: Index of the currently selected option.
123
+ options: List of (id, label) tuples for display.
124
+
125
+ Returns:
126
+ Rich markup string for the slide content.
127
+ """
128
+ content = "[bold cyan]📦 Model Subscription[/bold cyan]\n\n"
129
+ content += "[white]Do you have a model subscription?[/white]\n\n"
130
+
131
+ for i, (_, label) in enumerate(options):
132
+ if i == selected_option:
133
+ content += f"[bold green]▶ {label}[/bold green]\n"
134
+ else:
135
+ content += f"[dim] {label}[/dim]\n"
136
+
137
+ content += "\n\n"
138
+
139
+ # Dynamic content based on selection
140
+ selected_opt = options[selected_option][0] if options else None
141
+ if selected_opt == "chatgpt":
142
+ content += "[bold yellow]💡 ChatGPT Plus/Pro/Max[/bold yellow]\n\n"
143
+ content += "[green]OAuth login gives you access to:[/green]\n"
144
+ content += " • GPT-5.2\n"
145
+ content += " • GPT-5.2-codex\n"
146
+ content += " • No API key needed!\n"
147
+ elif selected_opt == "claude":
148
+ content += "[bold yellow]💡 Claude Code Pro/Max[/bold yellow]\n\n"
149
+ content += "[green]OAuth login gives you access to:[/green]\n"
150
+ content += " • Claude Opus 4.5\n"
151
+ content += " • Claude Sonnet 4.5\n"
152
+ content += " • Claude Haiku 4.5\n"
153
+ content += " • No API key needed!\n"
154
+ elif selected_opt == "api_keys":
155
+ content += "[bold yellow]💡 API Keys[/bold yellow]\n\n"
156
+ content += "[green]Use your own API keys for:[/green]\n"
157
+ content += " • OpenAI (GPT-5.2, GPT-5.2-codex)\n"
158
+ content += " • Anthropic (Opus/Sonnet/Haiku 4.5)\n"
159
+ content += " • Google (Gemini)\n"
160
+ content += " • And many more!\n"
161
+ elif selected_opt == "openrouter":
162
+ content += "[bold yellow]💡 OpenRouter[/bold yellow]\n\n"
163
+ content += "[green]Single API key for 100+ models:[/green]\n"
164
+ content += " • All major providers\n"
165
+ content += " • Pay-per-use pricing\n"
166
+ content += " • Great for exploration!\n"
167
+ elif selected_opt == "free":
168
+ content += "[bold yellow]💡 Free Tiers[/bold yellow]\n\n"
169
+ content += "[green]Explore free options:[/green]\n"
170
+ content += " • Google Gemini (free tier)\n"
171
+ content += " • Groq (fast inference)\n"
172
+ content += " • Local with Ollama\n"
173
+ else:
174
+ content += "[dim][Configure later using /set or /add_model][/dim]\n"
175
+
176
+ content += "\n\n[dim]Press → to continue[/dim]"
177
+ return content
178
+
179
+
180
+ def slide_api_keys(model_choice: str | None) -> str:
181
+ """Slide 2: API key setup information.
182
+
183
+ Args:
184
+ model_choice: User's model subscription selection from slide 1.
185
+
186
+ Returns:
187
+ Rich markup string for the slide content.
188
+ """
189
+ content = "[bold cyan]🔑 API Key Configuration[/bold cyan]\n\n"
190
+
191
+ if model_choice in ("chatgpt", "claude"):
192
+ content += "[green]✓ You selected OAuth login![/green]\n\n"
193
+ content += "[dim]After this wizard, we'll guide you\n"
194
+ content += "through the OAuth authentication flow.[/dim]\n\n"
195
+ content += "You can also add API keys for\n"
196
+ content += "additional providers:\n\n"
197
+ else:
198
+ content += "[white]Common API keys to configure:[/white]\n\n"
199
+
200
+ for key_name, description in API_KEYS_INFO:
201
+ content += f"[cyan]{key_name}[/cyan]\n"
202
+ content += f" [dim]{description}[/dim]\n"
203
+
204
+ content += "\n\n"
205
+ content += "[bold yellow]⚙️ Configuration[/bold yellow]\n\n"
206
+ content += "[green]Set API keys with:[/green]\n\n"
207
+ content += "[cyan]/set OPENAI_API_KEY=sk-...[/cyan]\n\n"
208
+ content += "[dim]Keys are stored securely in[/dim]\n"
209
+ content += "[dim]~/.config/code_puppy/puppy.cfg[/dim]\n\n"
210
+ content += "[green]Browse 1500+ models:[/green]\n"
211
+ content += "[cyan]/add_model[/cyan]\n"
212
+ content += "[dim]65+ providers available![/dim]"
213
+
214
+ return content
215
+
216
+
217
+ def slide_mcp_servers() -> str:
218
+ """Slide 3: MCP server information.
219
+
220
+ Returns:
221
+ Rich markup string for the slide content.
222
+ """
223
+ content = "[bold cyan]🔌 MCP Servers[/bold cyan]\n\n"
224
+ content += "[white]Extend Code Puppy with MCP![/white]\n\n"
225
+ content += "Model Context Protocol (MCP) lets you\n"
226
+ content += "add external tools and integrations.\n\n"
227
+ content += "[green]Commands:[/green]\n"
228
+ content += " [cyan]/mcp install[/cyan] - Browse curated catalog\n"
229
+ content += " [cyan]/mcp add[/cyan] - Add custom server\n"
230
+ content += " [cyan]/mcp list[/cyan] - View configured servers\n"
231
+ content += " [cyan]/mcp status[/cyan] - Check server health\n\n"
232
+ content += "[bold yellow]🌟 Popular MCP Servers[/bold yellow]\n\n"
233
+ content += "[green]@anthropic/mcp-server-github[/green]\n"
234
+ content += " GitHub integration\n\n"
235
+
236
+ content += "[green]@anthropic/mcp-server-postgres[/green]\n"
237
+ content += " Database access\n\n"
238
+ content += "[dim]Custom JSON configuration also supported[/dim]"
239
+
240
+ return content
241
+
242
+
243
+ def slide_appearance() -> str:
244
+ """Slide 4: Appearance customization.
245
+
246
+ Returns:
247
+ Rich markup string for the slide content.
248
+ """
249
+ content = "[bold cyan]🎨 Appearance[/bold cyan]\n\n"
250
+ content += "[white]Customize your Code Puppy experience![/white]\n\n"
251
+ content += "[green]Banner Colors:[/green]\n"
252
+ content += " [cyan]/colors[/cyan] - Customize tool banners\n"
253
+ content += " Change colors for THINKING, SHELL,\n"
254
+ content += " READ FILE, EDIT FILE, etc.\n\n"
255
+ content += "[green]Diff Highlighting:[/green]\n"
256
+ content += " [cyan]/diff[/cyan] - Syntax highlighting themes\n"
257
+ content += " Configure addition/deletion colors\n"
258
+ content += " with live preview!\n\n"
259
+ content += "[bold yellow]🖼️ Preview[/bold yellow]\n\n"
260
+ content += "[on blue] THINKING [/on blue] ⚡\n"
261
+ content += "[on dark_cyan] SHELL COMMAND [/on dark_cyan] 🚀\n"
262
+ content += "[on green] EDIT FILE [/on green] ✏️\n"
263
+ content += "[on purple] READ FILE [/on purple] 📂\n"
264
+ content += "[dim]All colors customizable![/dim]"
265
+
266
+ return content
267
+
268
+
269
+ def slide_agent_system() -> str:
270
+ """Slide 5: Agent system overview.
271
+
272
+ Returns:
273
+ Rich markup string for the slide content.
274
+ """
275
+ content = "[bold cyan]🤖 Agent System[/bold cyan]\n\n"
276
+ content += "[white]Code Puppy has specialized sub-agents![/white]\n\n"
277
+ content += "[green]Switch agents:[/green]\n"
278
+ content += " [cyan]/agent[/cyan] or [cyan]/a[/cyan]\n\n"
279
+ content += "[green]Key Agents:[/green]\n"
280
+ for _, name, desc in KEY_AGENTS:
281
+ content += f" {name}\n"
282
+ content += f" [dim]{desc}[/dim]\n"
283
+ content += "\n\n"
284
+ content += "[bold yellow]🔧 Agent Tips[/bold yellow]\n\n"
285
+ content += "[green]Create custom agents:[/green]\n"
286
+ content += "[cyan]/agent agent-creator[/cyan]\n"
287
+ content += "[dim]Agents are defined with JSON[/dim]\n"
288
+ content += "[dim]in ~/.code_puppy/agents/[/dim]\n\n"
289
+ content += "[green]Each agent has:[/green]\n"
290
+ content += " • Custom system prompt\n"
291
+ content += " • Selected tools\n"
292
+ content += " • Optional pinned model\n"
293
+
294
+ return content
295
+
296
+
297
+ def slide_model_pinning() -> str:
298
+ """Slide 6: Model pinning feature.
299
+
300
+ Returns:
301
+ Rich markup string for the slide content.
302
+ """
303
+ content = "[bold cyan]📌 Model Pinning[/bold cyan]\n\n"
304
+ content += "[white]Pin specific models to agents![/white]\n\n"
305
+ content += "[green]Command:[/green]\n"
306
+ content += " [cyan]/pin_model[/cyan]\n\n"
307
+ content += "[green]Example Multi-LLM Workflow:[/green]\n"
308
+ content += " [yellow]Planning:[/yellow] Kimi k2 (thinking)\n"
309
+ content += " [yellow]Implement:[/yellow] Claude Opus 4\n"
310
+ content += " [yellow]Testing:[/yellow] GLM 4.7\n"
311
+ content += " [yellow]Review:[/yellow] GPT-5.2-codex\n\n"
312
+ content += "[bold yellow]🎯 Why Pin Models?[/bold yellow]\n\n"
313
+ content += "Different models excel at\n"
314
+ content += "different tasks:\n\n"
315
+ content += "[green]Planning:[/green]\n"
316
+ content += " Deep reasoning models\n\n"
317
+ content += "[green]Coding:[/green]\n"
318
+ content += " Code-specialized models\n\n"
319
+ content += "[green]Review:[/green]\n"
320
+ content += " Critical analysis models\n\n"
321
+ content += "[dim]Mix and match for best results![/dim]"
322
+
323
+ return content
324
+
325
+
326
+ def slide_planning_agent() -> str:
327
+ """Slide 7: Planning agent power.
328
+
329
+ Returns:
330
+ Rich markup string for the slide content.
331
+ """
332
+ content = "[bold cyan]🚀 The Planning Agent[/bold cyan]\n\n"
333
+ content += "[bold yellow]Your Secret Weapon![/bold yellow]\n\n"
334
+ content += "The Planning Agent can:\n\n"
335
+ content += " ✓ Break down complex tasks\n"
336
+ content += " ✓ Create actionable roadmaps\n"
337
+ content += " ✓ Orchestrate sub-agents\n"
338
+ content += " ✓ Manage multi-step workflows\n\n"
339
+ content += "[green]Try it:[/green]\n"
340
+ content += " [cyan]/agent planning-agent[/cyan]\n"
341
+ content += "[dim]Then describe your project![/dim]\n\n"
342
+ content += "[bold yellow]💡 Example Prompt[/bold yellow]\n\n"
343
+ content += "[cyan]'Plan a REST API for a\n"
344
+ content += "todo app with auth,\n"
345
+ content += "database, and tests'[/cyan]\n\n"
346
+ content += "The Planning Agent will:\n\n"
347
+ content += "1. Analyze requirements\n"
348
+ content += "2. Break into phases\n"
349
+ content += "3. Create file structure\n"
350
+ content += "4. Delegate to specialists\n"
351
+ content += "5. Track progress\n"
352
+
353
+ return content
354
+
355
+
356
+ def slide_model_settings() -> str:
357
+ """Slide 8: Model settings.
358
+
359
+ Returns:
360
+ Rich markup string for the slide content.
361
+ """
362
+ content = "[bold cyan]⚙️ Model Settings[/bold cyan]\n\n"
363
+ content += "[white]Fine-tune model behavior![/white]\n\n"
364
+ content += "[green]Command:[/green]\n"
365
+ content += " [cyan]/model_settings[/cyan] or [cyan]/ms[/cyan]\n\n"
366
+ content += "[green]Configurable Parameters:[/green]\n"
367
+ content += " [yellow]temperature[/yellow] - Creativity (0.0-2.0)\n"
368
+ content += " [yellow]max_tokens[/yellow] - Response length\n"
369
+ content += " [yellow]top_p[/yellow] - Nucleus sampling\n"
370
+ content += " [yellow]presence_penalty[/yellow] - Topic diversity\n\n"
371
+ content += "[bold yellow]🎛️ Common Settings[/bold yellow]\n\n"
372
+ content += "[green]Precise code:[/green]\n"
373
+ content += " temperature: 0.0-0.3\n\n"
374
+ content += "[green]Creative writing:[/green]\n"
375
+ content += " temperature: 0.7-1.0\n\n"
376
+ content += "[green]Long outputs:[/green]\n"
377
+ content += " max_tokens: 4096+\n\n"
378
+ content += "[dim]Settings persist per-session[/dim]"
379
+
380
+ return content
381
+
382
+
383
+ def slide_complete(trigger_oauth: str | None) -> str:
384
+ """Slide 9: Completion.
385
+
386
+ Args:
387
+ trigger_oauth: OAuth provider that was selected ("chatgpt"/"claude"/None).
388
+
389
+ Returns:
390
+ Rich markup string for the slide content.
391
+ """
392
+ content = "[bold green]🎉 You're All Set![/bold green]\n\n"
393
+ content += "[white]Code Puppy is ready to help![/white]\n\n"
394
+ content += "[bold cyan]Quick Reference:[/bold cyan]\n\n"
395
+ content += " [cyan]/model[/cyan] - Switch models\n"
396
+ content += " [cyan]/agent[/cyan] - Switch agents\n"
397
+ content += " [cyan]/set[/cyan] - Configure settings\n"
398
+ content += " [cyan]/add_model[/cyan] - Browse 1500+ models\n"
399
+ content += " [cyan]/mcp[/cyan] - MCP server management\n"
400
+ content += " [cyan]/help[/cyan] - Full command list\n\n"
401
+ content += "[bold yellow]Press Enter to start coding! 🐶[/bold yellow]\n"
402
+ content += "\n"
403
+ content += "[bold yellow]🐾 Happy Coding![/bold yellow]\n\n"
404
+ content += "[dim]Remember:[/dim]\n"
405
+ content += "• Be specific in prompts\n"
406
+ content += "• Let agents read files first\n"
407
+ content += "• Use planning for complex tasks\n"
408
+ content += "• Check diffs before applying\n\n"
409
+ content += "[green]Community:[/green]\n"
410
+ content += " GitHub: code-puppy\n"
411
+ content += " Discord: code-puppy\n"
412
+
413
+ if trigger_oauth:
414
+ content += f"\n[bold cyan]Next: {trigger_oauth.title()} OAuth[/bold cyan]"
415
+
416
+ return content