prompt_manager 0.5.7 → 0.5.8

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/COMMITS.md +196 -0
  4. data/README.md +485 -203
  5. data/docs/.keep +0 -0
  6. data/docs/advanced/custom-keywords.md +421 -0
  7. data/docs/advanced/dynamic-directives.md +535 -0
  8. data/docs/advanced/performance.md +612 -0
  9. data/docs/advanced/search-integration.md +635 -0
  10. data/docs/api/configuration.md +355 -0
  11. data/docs/api/directive-processor.md +431 -0
  12. data/docs/api/prompt-class.md +354 -0
  13. data/docs/api/storage-adapters.md +462 -0
  14. data/docs/assets/favicon.ico +1 -0
  15. data/docs/assets/logo.svg +24 -0
  16. data/docs/core-features/comments.md +48 -0
  17. data/docs/core-features/directive-processing.md +38 -0
  18. data/docs/core-features/erb-integration.md +68 -0
  19. data/docs/core-features/error-handling.md +197 -0
  20. data/docs/core-features/parameter-history.md +76 -0
  21. data/docs/core-features/parameterized-prompts.md +500 -0
  22. data/docs/core-features/shell-integration.md +79 -0
  23. data/docs/development/architecture.md +544 -0
  24. data/docs/development/contributing.md +425 -0
  25. data/docs/development/roadmap.md +234 -0
  26. data/docs/development/testing.md +822 -0
  27. data/docs/examples/advanced.md +523 -0
  28. data/docs/examples/basic.md +688 -0
  29. data/docs/examples/real-world.md +776 -0
  30. data/docs/examples.md +337 -0
  31. data/docs/getting-started/basic-concepts.md +318 -0
  32. data/docs/getting-started/installation.md +97 -0
  33. data/docs/getting-started/quick-start.md +256 -0
  34. data/docs/index.md +230 -0
  35. data/docs/migration/v0.9.0.md +459 -0
  36. data/docs/migration/v1.0.0.md +591 -0
  37. data/docs/storage/activerecord-adapter.md +348 -0
  38. data/docs/storage/custom-adapters.md +176 -0
  39. data/docs/storage/filesystem-adapter.md +236 -0
  40. data/docs/storage/overview.md +427 -0
  41. data/examples/advanced_integrations.rb +52 -0
  42. data/examples/prompts_dir/advanced_demo.txt +79 -0
  43. data/examples/prompts_dir/directive_example.json +1 -0
  44. data/examples/prompts_dir/directive_example.txt +8 -0
  45. data/examples/prompts_dir/todo.json +1 -1
  46. data/improvement_plan.md +996 -0
  47. data/lib/prompt_manager/storage/file_system_adapter.rb +8 -2
  48. data/lib/prompt_manager/version.rb +1 -1
  49. data/mkdocs.yml +146 -0
  50. data/prompt_manager_logo.png +0 -0
  51. metadata +46 -3
  52. data/LICENSE.txt +0 -21
@@ -0,0 +1,688 @@
1
+ # Basic Examples
2
+
3
+ This section provides practical, ready-to-use examples that demonstrate PromptManager's core functionality. Each example includes complete code and explanations.
4
+
5
+ ## Setup
6
+
7
+ All examples assume this basic setup:
8
+
9
+ ```ruby
10
+ require 'prompt_manager'
11
+
12
+ # Configure FileSystem adapter
13
+ PromptManager::Prompt.storage_adapter =
14
+ PromptManager::Storage::FileSystemAdapter.config do |config|
15
+ config.prompts_dir = File.expand_path('~/.prompts')
16
+ end.new
17
+ ```
18
+
19
+ ## Example 1: Simple Greeting
20
+
21
+ The classic "Hello World" example for prompts.
22
+
23
+ ### Prompt File
24
+
25
+ ```text title="~/.prompts/greeting.txt"
26
+ # Simple greeting prompt
27
+ # Keywords: NAME
28
+
29
+ Hello [NAME]! Welcome to PromptManager.
30
+
31
+ How can I help you today?
32
+ ```
33
+
34
+ ### Parameters File
35
+
36
+ ```json title="~/.prompts/greeting.json"
37
+ {
38
+ "[NAME]": ["World", "Alice", "Bob"]
39
+ }
40
+ ```
41
+
42
+ ### Ruby Code
43
+
44
+ ```ruby title="greeting_example.rb"
45
+ #!/usr/bin/env ruby
46
+ require 'prompt_manager'
47
+
48
+ # Configure storage
49
+ PromptManager::Prompt.storage_adapter =
50
+ PromptManager::Storage::FileSystemAdapter.config do |config|
51
+ config.prompts_dir = File.expand_path('~/.prompts')
52
+ end.new
53
+
54
+ # Load and use the prompt
55
+ prompt = PromptManager::Prompt.new(id: 'greeting')
56
+ prompt.parameters['[NAME]'] = 'Alice'
57
+
58
+ puts prompt.to_s
59
+ # Output: Hello Alice! Welcome to PromptManager.\n\nHow can I help you today?
60
+ ```
61
+
62
+ **Key Learning Points:**
63
+ - Basic prompt loading with `new(id: 'greeting')`
64
+ - Parameter setting with direct assignment
65
+ - Text generation with `to_s`
66
+
67
+ ## Example 2: Email Template
68
+
69
+ A more realistic example showing email template management.
70
+
71
+ ### Prompt File
72
+
73
+ ```text title="~/.prompts/welcome_email.txt"
74
+ # Welcome email template
75
+ # Keywords: USER_NAME, COMPANY_NAME, LOGIN_URL, SUPPORT_EMAIL
76
+
77
+ Subject: Welcome to [COMPANY_NAME]!
78
+
79
+ Dear [USER_NAME],
80
+
81
+ Welcome to [COMPANY_NAME]! We're excited to have you join our community.
82
+
83
+ To get started:
84
+ 1. Log in to your account: [LOGIN_URL]
85
+ 2. Complete your profile setup
86
+ 3. Explore our features
87
+
88
+ If you need any help, don't hesitate to contact us at [SUPPORT_EMAIL].
89
+
90
+ Best regards,
91
+ The [COMPANY_NAME] Team
92
+ ```
93
+
94
+ ### Ruby Code
95
+
96
+ ```ruby title="email_example.rb"
97
+ require 'prompt_manager'
98
+
99
+ class WelcomeEmailGenerator
100
+ def initialize
101
+ @prompt = PromptManager::Prompt.new(id: 'welcome_email')
102
+ end
103
+
104
+ def generate_for_user(user_data)
105
+ @prompt.parameters = {
106
+ '[USER_NAME]' => user_data[:name],
107
+ '[COMPANY_NAME]' => 'Acme Corp',
108
+ '[LOGIN_URL]' => 'https://app.acme.com/login',
109
+ '[SUPPORT_EMAIL]' => 'support@acme.com'
110
+ }
111
+
112
+ @prompt.to_s
113
+ end
114
+ end
115
+
116
+ # Usage
117
+ generator = WelcomeEmailGenerator.new
118
+ user = { name: 'Alice Johnson', email: 'alice@example.com' }
119
+
120
+ email_content = generator.generate_for_user(user)
121
+ puts email_content
122
+
123
+ # Save parameters for future use
124
+ generator.instance_variable_get(:@prompt).save
125
+ ```
126
+
127
+ **Key Learning Points:**
128
+ - Organizing prompt logic in classes
129
+ - Batch parameter assignment with hash
130
+ - Saving parameter changes back to storage
131
+
132
+ ## Example 3: Dynamic Content with ERB
133
+
134
+ Using ERB for conditional content and dynamic generation.
135
+
136
+ ### Prompt File
137
+
138
+ ```text title="~/.prompts/order_confirmation.txt"
139
+ # Order confirmation with dynamic content
140
+ # Keywords: CUSTOMER_NAME, ORDER_NUMBER, ITEM_COUNT, TOTAL_AMOUNT, IS_PREMIUM
141
+
142
+ Dear [CUSTOMER_NAME],
143
+
144
+ Thank you for your order #[ORDER_NUMBER]!
145
+
146
+ <% item_count = '[ITEM_COUNT]'.to_i %>
147
+ Your order contains <%= item_count %> item<%= 's' if item_count != 1 %>.
148
+
149
+ <% if '[IS_PREMIUM]' == 'true' %>
150
+ 🌟 As a premium member, you'll receive:
151
+ - Free express shipping
152
+ - Priority customer support
153
+ - Extended warranty on all items
154
+ <% else %>
155
+ Standard shipping will be applied to your order.
156
+ <% end %>
157
+
158
+ Order Total: $[TOTAL_AMOUNT]
159
+
160
+ <% if '[TOTAL_AMOUNT]'.to_f > 100 %>
161
+ 🎉 Congratulations! You qualify for free shipping!
162
+ <% end %>
163
+
164
+ Best regards,
165
+ Customer Service Team
166
+ ```
167
+
168
+ ### Ruby Code
169
+
170
+ ```ruby title="order_confirmation_example.rb"
171
+ require 'prompt_manager'
172
+
173
+ class OrderConfirmation
174
+ def initialize
175
+ # Enable ERB processing
176
+ @prompt = PromptManager::Prompt.new(
177
+ id: 'order_confirmation',
178
+ erb_flag: true
179
+ )
180
+ end
181
+
182
+ def generate(order)
183
+ @prompt.parameters = {
184
+ '[CUSTOMER_NAME]' => order[:customer_name],
185
+ '[ORDER_NUMBER]' => order[:order_number],
186
+ '[ITEM_COUNT]' => order[:items].count.to_s,
187
+ '[TOTAL_AMOUNT]' => sprintf('%.2f', order[:total]),
188
+ '[IS_PREMIUM]' => order[:premium_member].to_s
189
+ }
190
+
191
+ @prompt.to_s
192
+ end
193
+ end
194
+
195
+ # Usage with different order types
196
+ confirmation = OrderConfirmation.new
197
+
198
+ # Regular customer order
199
+ regular_order = {
200
+ customer_name: 'John Smith',
201
+ order_number: 'ORD-12345',
202
+ items: ['Widget A', 'Widget B'],
203
+ total: 85.50,
204
+ premium_member: false
205
+ }
206
+
207
+ puts "=== Regular Order ==="
208
+ puts confirmation.generate(regular_order)
209
+
210
+ # Premium customer order
211
+ premium_order = {
212
+ customer_name: 'Jane Doe',
213
+ order_number: 'ORD-12346',
214
+ items: ['Premium Widget', 'Deluxe Kit', 'Accessories'],
215
+ total: 150.00,
216
+ premium_member: true
217
+ }
218
+
219
+ puts "\n=== Premium Order ==="
220
+ puts confirmation.generate(premium_order)
221
+ ```
222
+
223
+ **Key Learning Points:**
224
+ - Enabling ERB with `erb_flag: true`
225
+ - Conditional content using ERB syntax
226
+ - Dynamic content generation based on parameter values
227
+
228
+ ## Example 4: Directive Processing
229
+
230
+ Using directives to include shared content and build modular prompts.
231
+
232
+ ### Shared Header File
233
+
234
+ ```text title="~/.prompts/common/header.txt"
235
+ =====================================
236
+ ACME CORPORATION
237
+ Customer Service Division
238
+ =====================================
239
+
240
+ Date: <%= Date.today.strftime('%B %d, %Y') %>
241
+ ```
242
+
243
+ ### Shared Footer File
244
+
245
+ ```text title="~/.prompts/common/footer.txt"
246
+ =====================================
247
+
248
+ For immediate assistance:
249
+ 📞 Call: 1-800-ACME-HELP
250
+ 📧 Email: support@acme.com
251
+ 🌐 Web: https://help.acme.com
252
+
253
+ Office Hours: Monday-Friday, 9 AM - 6 PM EST
254
+ ```
255
+
256
+ ### Main Prompt File
257
+
258
+ ```text title="~/.prompts/customer_response.txt"
259
+ # Customer service response template
260
+ # Keywords: CUSTOMER_NAME, ISSUE_TYPE, RESOLUTION_TIME, AGENT_NAME
261
+
262
+ //include common/header.txt
263
+
264
+ Dear [CUSTOMER_NAME],
265
+
266
+ Thank you for contacting us regarding your [ISSUE_TYPE] issue.
267
+
268
+ We understand your concern and want to resolve this as quickly as possible.
269
+ Based on our initial review, we expect to have this resolved within [RESOLUTION_TIME].
270
+
271
+ I'll personally be handling your case and will keep you updated on our progress.
272
+
273
+ Best regards,
274
+ [AGENT_NAME]
275
+ Customer Service Representative
276
+
277
+ //include common/footer.txt
278
+ ```
279
+
280
+ ### Ruby Code
281
+
282
+ ```ruby title="customer_response_example.rb"
283
+ require 'prompt_manager'
284
+
285
+ class CustomerServiceResponse
286
+ def initialize
287
+ @prompt = PromptManager::Prompt.new(
288
+ id: 'customer_response',
289
+ erb_flag: true # Enable ERB for header date processing
290
+ )
291
+ end
292
+
293
+ def generate_response(case_data)
294
+ @prompt.parameters = {
295
+ '[CUSTOMER_NAME]' => case_data[:customer_name],
296
+ '[ISSUE_TYPE]' => case_data[:issue_type],
297
+ '[RESOLUTION_TIME]' => case_data[:expected_resolution],
298
+ '[AGENT_NAME]' => case_data[:agent_name]
299
+ }
300
+
301
+ @prompt.to_s
302
+ end
303
+ end
304
+
305
+ # Usage
306
+ response_generator = CustomerServiceResponse.new
307
+
308
+ customer_case = {
309
+ customer_name: 'Sarah Wilson',
310
+ issue_type: 'billing discrepancy',
311
+ expected_resolution: '2-3 business days',
312
+ agent_name: 'Mike Johnson'
313
+ }
314
+
315
+ puts response_generator.generate_response(customer_case)
316
+ ```
317
+
318
+ **Key Learning Points:**
319
+ - Using `//include` directives for shared content
320
+ - Combining ERB and directive processing
321
+ - Building modular, reusable prompt components
322
+
323
+ ## Example 5: Parameter History and Management
324
+
325
+ Leveraging parameter history for better user experience.
326
+
327
+ ### Ruby Code
328
+
329
+ ```ruby title="parameter_history_example.rb"
330
+ require 'prompt_manager'
331
+
332
+ class PromptWithHistory
333
+ def initialize(prompt_id)
334
+ @prompt = PromptManager::Prompt.new(id: prompt_id)
335
+ end
336
+
337
+ def set_parameter(key, value)
338
+ # Get current history
339
+ current_history = @prompt.parameters[key] || []
340
+
341
+ # Add new value if it's different from the last one
342
+ unless current_history.last == value
343
+ current_history << value
344
+ # Keep only last 10 values
345
+ current_history = current_history.last(10)
346
+ end
347
+
348
+ @prompt.parameters[key] = current_history
349
+ @prompt.save
350
+ end
351
+
352
+ def get_parameter_history(key)
353
+ @prompt.parameters[key] || []
354
+ end
355
+
356
+ def get_current_parameter(key)
357
+ history = get_parameter_history(key)
358
+ history.empty? ? nil : history.last
359
+ end
360
+
361
+ def get_parameter_suggestions(key, limit = 5)
362
+ history = get_parameter_history(key)
363
+ history.reverse.take(limit)
364
+ end
365
+
366
+ def generate
367
+ @prompt.to_s
368
+ end
369
+ end
370
+
371
+ # Usage example
372
+ class InteractivePromptBuilder
373
+ def initialize
374
+ @prompt_manager = PromptWithHistory.new('greeting')
375
+ end
376
+
377
+ def interactive_session
378
+ puts "=== Interactive Prompt Builder ==="
379
+ puts "Available keywords: #{@prompt_manager.instance_variable_get(:@prompt).keywords.join(', ')}"
380
+
381
+ @prompt_manager.instance_variable_get(:@prompt).keywords.each do |keyword|
382
+ # Show previous values
383
+ suggestions = @prompt_manager.get_parameter_suggestions(keyword)
384
+
385
+ if suggestions.any?
386
+ puts "\nPrevious values for #{keyword}:"
387
+ suggestions.each_with_index do |value, index|
388
+ puts " #{index + 1}. #{value}"
389
+ end
390
+ puts " #{suggestions.length + 1}. Enter new value"
391
+
392
+ print "Choose option or enter new value: "
393
+ input = gets.chomp
394
+
395
+ if input.to_i.between?(1, suggestions.length)
396
+ selected_value = suggestions[input.to_i - 1]
397
+ @prompt_manager.set_parameter(keyword, selected_value)
398
+ puts "Selected: #{selected_value}"
399
+ else
400
+ @prompt_manager.set_parameter(keyword, input)
401
+ puts "New value saved: #{input}"
402
+ end
403
+ else
404
+ print "Enter value for #{keyword}: "
405
+ value = gets.chomp
406
+ @prompt_manager.set_parameter(keyword, value)
407
+ end
408
+ end
409
+
410
+ puts "\n=== Generated Prompt ==="
411
+ puts @prompt_manager.generate
412
+ end
413
+ end
414
+
415
+ # Run interactive session
416
+ # InteractivePromptBuilder.new.interactive_session
417
+ ```
418
+
419
+ **Key Learning Points:**
420
+ - Working with parameter history arrays
421
+ - Building user-friendly parameter selection
422
+ - Maintaining parameter history across sessions
423
+
424
+ ## Example 6: Error Handling
425
+
426
+ Robust error handling for production use.
427
+
428
+ ### Ruby Code
429
+
430
+ ```ruby title="error_handling_example.rb"
431
+ require 'prompt_manager'
432
+
433
+ class RobustPromptProcessor
434
+ def initialize(prompt_id)
435
+ @prompt_id = prompt_id
436
+ @prompt = nil
437
+ end
438
+
439
+ def process_with_fallback(parameters, fallback_text = nil)
440
+ begin
441
+ # Attempt to load prompt
442
+ @prompt = PromptManager::Prompt.new(id: @prompt_id)
443
+
444
+ # Validate required parameters
445
+ validate_parameters(parameters)
446
+
447
+ # Set parameters
448
+ @prompt.parameters = parameters
449
+
450
+ # Generate text
451
+ result = @prompt.to_s
452
+
453
+ # Check for unreplaced keywords
454
+ check_unreplaced_keywords(result)
455
+
456
+ { success: true, text: result }
457
+
458
+ rescue PromptManager::StorageError => e
459
+ handle_storage_error(e, fallback_text)
460
+ rescue PromptManager::ParameterError => e
461
+ handle_parameter_error(e)
462
+ rescue => e
463
+ handle_unexpected_error(e, fallback_text)
464
+ ensure
465
+ # Always try to save any parameter changes
466
+ save_parameters_safely if @prompt
467
+ end
468
+ end
469
+
470
+ private
471
+
472
+ def validate_parameters(parameters)
473
+ return unless @prompt
474
+
475
+ required_keywords = @prompt.keywords
476
+ provided_keywords = parameters.keys
477
+ missing = required_keywords - provided_keywords
478
+
479
+ unless missing.empty?
480
+ raise PromptManager::ParameterError, "Missing required parameters: #{missing.join(', ')}"
481
+ end
482
+ end
483
+
484
+ def check_unreplaced_keywords(text)
485
+ # Look for unreplaced keywords (basic pattern)
486
+ unreplaced = text.scan(/\[([A-Z_\s]+)\]/).flatten
487
+
488
+ if unreplaced.any?
489
+ puts "⚠️ Warning: Found unreplaced keywords: #{unreplaced.join(', ')}"
490
+ end
491
+ end
492
+
493
+ def handle_storage_error(error, fallback_text)
494
+ puts "❌ Storage Error: #{error.message}"
495
+
496
+ if fallback_text
497
+ puts "📄 Using fallback text"
498
+ { success: false, text: fallback_text, error: :storage_error }
499
+ else
500
+ { success: false, error: :storage_error, message: error.message }
501
+ end
502
+ end
503
+
504
+ def handle_parameter_error(error)
505
+ puts "❌ Parameter Error: #{error.message}"
506
+ { success: false, error: :parameter_error, message: error.message }
507
+ end
508
+
509
+ def handle_unexpected_error(error, fallback_text)
510
+ puts "❌ Unexpected Error: #{error.class} - #{error.message}"
511
+ puts error.backtrace.first(3) if ENV['DEBUG']
512
+
513
+ if fallback_text
514
+ { success: false, text: fallback_text, error: :unexpected_error }
515
+ else
516
+ { success: false, error: :unexpected_error, message: error.message }
517
+ end
518
+ end
519
+
520
+ def save_parameters_safely
521
+ @prompt.save
522
+ rescue => e
523
+ puts "⚠️ Warning: Could not save parameters: #{e.message}"
524
+ end
525
+ end
526
+
527
+ # Usage examples
528
+ processor = RobustPromptProcessor.new('welcome_email')
529
+
530
+ # Successful processing
531
+ result = processor.process_with_fallback({
532
+ '[USER_NAME]' => 'Alice',
533
+ '[COMPANY_NAME]' => 'Acme Corp'
534
+ })
535
+
536
+ puts "Success: #{result[:success]}"
537
+ puts result[:text] if result[:success]
538
+
539
+ # Error handling with fallback
540
+ fallback = "Welcome! Thank you for joining us."
541
+
542
+ result = processor.process_with_fallback(
543
+ { '[USER_NAME]' => 'Bob' }, # Missing required parameter
544
+ fallback
545
+ )
546
+
547
+ puts "Success: #{result[:success]}"
548
+ puts "Error: #{result[:error]}" unless result[:success]
549
+ puts "Text: #{result[:text]}" if result[:text]
550
+ ```
551
+
552
+ **Key Learning Points:**
553
+ - Comprehensive error handling for all error types
554
+ - Graceful fallback strategies
555
+ - Parameter validation and safety checks
556
+ - Production-ready error reporting
557
+
558
+ ## Example 7: Batch Processing
559
+
560
+ Processing multiple prompts efficiently.
561
+
562
+ ### Ruby Code
563
+
564
+ ```ruby title="batch_processing_example.rb"
565
+ require 'prompt_manager'
566
+
567
+ class BatchPromptProcessor
568
+ def initialize
569
+ @results = []
570
+ @errors = []
571
+ end
572
+
573
+ def process_batch(prompt_configs)
574
+ prompt_configs.each_with_index do |config, index|
575
+ begin
576
+ result = process_single_prompt(config)
577
+ @results << { index: index, config: config, result: result }
578
+ puts "✅ Processed #{config[:id]} successfully"
579
+ rescue => e
580
+ error = { index: index, config: config, error: e }
581
+ @errors << error
582
+ puts "❌ Failed to process #{config[:id]}: #{e.message}"
583
+ end
584
+ end
585
+
586
+ summary
587
+ end
588
+
589
+ def process_single_prompt(config)
590
+ prompt = PromptManager::Prompt.new(
591
+ id: config[:id],
592
+ erb_flag: config[:erb_flag] || false
593
+ )
594
+
595
+ prompt.parameters = config[:parameters]
596
+ prompt.to_s
597
+ end
598
+
599
+ def summary
600
+ {
601
+ total: @results.length + @errors.length,
602
+ successful: @results.length,
603
+ failed: @errors.length,
604
+ results: @results,
605
+ errors: @errors
606
+ }
607
+ end
608
+
609
+ def successful_results
610
+ @results.map { |r| r[:result] }
611
+ end
612
+
613
+ def failed_configs
614
+ @errors.map { |e| e[:config] }
615
+ end
616
+ end
617
+
618
+ # Usage
619
+ batch_configs = [
620
+ {
621
+ id: 'greeting',
622
+ parameters: { '[NAME]' => 'Alice' }
623
+ },
624
+ {
625
+ id: 'welcome_email',
626
+ parameters: {
627
+ '[USER_NAME]' => 'Bob',
628
+ '[COMPANY_NAME]' => 'Acme Corp',
629
+ '[LOGIN_URL]' => 'https://app.acme.com',
630
+ '[SUPPORT_EMAIL]' => 'support@acme.com'
631
+ }
632
+ },
633
+ {
634
+ id: 'order_confirmation',
635
+ erb_flag: true,
636
+ parameters: {
637
+ '[CUSTOMER_NAME]' => 'Charlie',
638
+ '[ORDER_NUMBER]' => 'ORD-789',
639
+ '[ITEM_COUNT]' => '3',
640
+ '[TOTAL_AMOUNT]' => '199.99',
641
+ '[IS_PREMIUM]' => 'true'
642
+ }
643
+ }
644
+ ]
645
+
646
+ processor = BatchPromptProcessor.new
647
+ summary = processor.process_batch(batch_configs)
648
+
649
+ puts "\n=== Batch Processing Summary ==="
650
+ puts "Total: #{summary[:total]}"
651
+ puts "Successful: #{summary[:successful]}"
652
+ puts "Failed: #{summary[:failed]}"
653
+
654
+ if summary[:failed] > 0
655
+ puts "\nFailed prompts:"
656
+ processor.failed_configs.each do |config|
657
+ puts " - #{config[:id]}"
658
+ end
659
+ end
660
+ ```
661
+
662
+ **Key Learning Points:**
663
+ - Batch processing patterns
664
+ - Error collection and reporting
665
+ - Processing summaries and statistics
666
+ - Handling mixed success/failure scenarios
667
+
668
+ ## Running the Examples
669
+
670
+ 1. **Create the prompts directory:**
671
+ ```bash
672
+ mkdir -p ~/.prompts/common
673
+ ```
674
+
675
+ 2. **Create the prompt files** shown in each example
676
+
677
+ 3. **Run any example:**
678
+ ```bash
679
+ ruby greeting_example.rb
680
+ ruby email_example.rb
681
+ # etc.
682
+ ```
683
+
684
+ ## Next Steps
685
+
686
+ - **Advanced Examples**: See [Advanced Examples](advanced.md) for complex scenarios
687
+ - **Real World Cases**: Check [Real World Use Cases](real-world.md) for production examples
688
+ - **Core Features**: Learn more about [Parameterized Prompts](../core-features/parameterized-prompts.md)