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,462 @@
1
+ # Storage Adapters API Reference
2
+
3
+ PromptManager uses a storage adapter pattern to provide flexible backends for prompt storage and retrieval.
4
+
5
+ ## Base Storage Adapter
6
+
7
+ All storage adapters inherit from `PromptManager::Storage::Base` and must implement the core interface.
8
+
9
+ ### `PromptManager::Storage::Base`
10
+
11
+ The abstract base class that defines the storage adapter interface.
12
+
13
+ #### Required Methods
14
+
15
+ ##### `read(prompt_id)`
16
+
17
+ Reads prompt content from storage.
18
+
19
+ **Parameters:**
20
+ - `prompt_id` (String): Unique identifier for the prompt
21
+
22
+ **Returns:** String - The prompt content
23
+
24
+ **Raises:**
25
+ - `PromptManager::PromptNotFoundError` - If prompt doesn't exist
26
+ - `PromptManager::StorageError` - For storage-related errors
27
+
28
+ ```ruby
29
+ def read(prompt_id)
30
+ # Implementation must return prompt content as string
31
+ # or raise PromptNotFoundError if not found
32
+ end
33
+ ```
34
+
35
+ ##### `write(prompt_id, content)`
36
+
37
+ Writes prompt content to storage.
38
+
39
+ **Parameters:**
40
+ - `prompt_id` (String): Unique identifier for the prompt
41
+ - `content` (String): The prompt content to store
42
+
43
+ **Returns:** Boolean - True on success
44
+
45
+ **Raises:**
46
+ - `PromptManager::StorageError` - For storage-related errors
47
+
48
+ ```ruby
49
+ def write(prompt_id, content)
50
+ # Implementation must store content and return true
51
+ # or raise StorageError on failure
52
+ end
53
+ ```
54
+
55
+ ##### `exist?(prompt_id)`
56
+
57
+ Checks if a prompt exists in storage.
58
+
59
+ **Parameters:**
60
+ - `prompt_id` (String): Unique identifier for the prompt
61
+
62
+ **Returns:** Boolean - True if prompt exists
63
+
64
+ ```ruby
65
+ def exist?(prompt_id)
66
+ # Implementation must return boolean
67
+ end
68
+ ```
69
+
70
+ ##### `delete(prompt_id)`
71
+
72
+ Removes a prompt from storage.
73
+
74
+ **Parameters:**
75
+ - `prompt_id` (String): Unique identifier for the prompt
76
+
77
+ **Returns:** Boolean - True if successfully deleted
78
+
79
+ ```ruby
80
+ def delete(prompt_id)
81
+ # Implementation must remove prompt and return success status
82
+ end
83
+ ```
84
+
85
+ ##### `list`
86
+
87
+ Returns all available prompt identifiers.
88
+
89
+ **Returns:** Array<String> - Array of prompt IDs
90
+
91
+ ```ruby
92
+ def list
93
+ # Implementation must return array of all prompt IDs
94
+ end
95
+ ```
96
+
97
+ #### Optional Methods
98
+
99
+ ##### `initialize(**options)`
100
+
101
+ Constructor for storage adapter configuration.
102
+
103
+ ```ruby
104
+ def initialize(**options)
105
+ super
106
+ # Custom initialization logic
107
+ end
108
+ ```
109
+
110
+ ##### `clear`
111
+
112
+ Removes all prompts from storage (optional).
113
+
114
+ **Returns:** Boolean - True on success
115
+
116
+ ```ruby
117
+ def clear
118
+ # Optional: implement to support clearing all prompts
119
+ end
120
+ ```
121
+
122
+ ## Built-in Storage Adapters
123
+
124
+ ### FileSystemAdapter
125
+
126
+ Stores prompts as files in a directory structure.
127
+
128
+ ```ruby
129
+ adapter = PromptManager::Storage::FileSystemAdapter.new(
130
+ prompts_dir: '/path/to/prompts',
131
+ file_extensions: ['.txt', '.md', '.prompt'],
132
+ create_directories: true
133
+ )
134
+ ```
135
+
136
+ **Configuration Options:**
137
+
138
+ - `prompts_dir` (String|Array): Directory path(s) to search
139
+ - `file_extensions` (Array): File extensions to recognize (default: `['.txt', '.md']`)
140
+ - `create_directories` (Boolean): Create directories if they don't exist (default: `true`)
141
+
142
+ **Features:**
143
+ - Hierarchical prompt organization with subdirectories
144
+ - Multiple search paths with fallback
145
+ - Automatic file extension detection
146
+ - Thread-safe file operations
147
+
148
+ ### ActiveRecordAdapter
149
+
150
+ Stores prompts in a database using ActiveRecord.
151
+
152
+ ```ruby
153
+ adapter = PromptManager::Storage::ActiveRecordAdapter.new(
154
+ model_class: Prompt,
155
+ id_column: :prompt_id,
156
+ content_column: :content,
157
+ scope: -> { where(active: true) }
158
+ )
159
+ ```
160
+
161
+ **Configuration Options:**
162
+
163
+ - `model_class` (Class): ActiveRecord model class
164
+ - `id_column` (Symbol): Column containing prompt ID (default: `:prompt_id`)
165
+ - `content_column` (Symbol): Column containing prompt content (default: `:content`)
166
+ - `scope` (Proc): Additional query scope (optional)
167
+
168
+ **Features:**
169
+ - Full database integration with Rails
170
+ - Transaction support
171
+ - Query optimization
172
+ - Multi-tenancy support
173
+
174
+ ## Custom Adapter Implementation
175
+
176
+ ### Example: MemoryAdapter
177
+
178
+ ```ruby
179
+ class MemoryAdapter < PromptManager::Storage::Base
180
+ def initialize(**options)
181
+ super
182
+ @prompts = {}
183
+ @mutex = Mutex.new
184
+ end
185
+
186
+ def read(prompt_id)
187
+ @mutex.synchronize do
188
+ content = @prompts[prompt_id]
189
+ raise PromptManager::PromptNotFoundError.new("Prompt '#{prompt_id}' not found") unless content
190
+ content
191
+ end
192
+ end
193
+
194
+ def write(prompt_id, content)
195
+ @mutex.synchronize do
196
+ @prompts[prompt_id] = content
197
+ end
198
+ true
199
+ end
200
+
201
+ def exist?(prompt_id)
202
+ @mutex.synchronize { @prompts.key?(prompt_id) }
203
+ end
204
+
205
+ def delete(prompt_id)
206
+ @mutex.synchronize do
207
+ @prompts.delete(prompt_id) ? true : false
208
+ end
209
+ end
210
+
211
+ def list
212
+ @mutex.synchronize { @prompts.keys }
213
+ end
214
+
215
+ def clear
216
+ @mutex.synchronize { @prompts.clear }
217
+ true
218
+ end
219
+ end
220
+ ```
221
+
222
+ ### Example: HTTPAdapter
223
+
224
+ ```ruby
225
+ require 'net/http'
226
+ require 'json'
227
+
228
+ class HTTPAdapter < PromptManager::Storage::Base
229
+ def initialize(base_url:, api_token: nil, **options)
230
+ super(**options)
231
+ @base_url = base_url.chomp('/')
232
+ @api_token = api_token
233
+ end
234
+
235
+ def read(prompt_id)
236
+ response = http_get("/prompts/#{prompt_id}")
237
+
238
+ case response.code
239
+ when '200'
240
+ JSON.parse(response.body)['content']
241
+ when '404'
242
+ raise PromptManager::PromptNotFoundError.new("Prompt '#{prompt_id}' not found")
243
+ else
244
+ raise PromptManager::StorageError.new("HTTP error: #{response.code}")
245
+ end
246
+ end
247
+
248
+ def write(prompt_id, content)
249
+ body = { content: content }.to_json
250
+ response = http_post("/prompts/#{prompt_id}", body)
251
+
252
+ response.code == '200' || response.code == '201'
253
+ end
254
+
255
+ def exist?(prompt_id)
256
+ response = http_head("/prompts/#{prompt_id}")
257
+ response.code == '200'
258
+ rescue
259
+ false
260
+ end
261
+
262
+ def delete(prompt_id)
263
+ response = http_delete("/prompts/#{prompt_id}")
264
+ response.code == '200' || response.code == '204'
265
+ end
266
+
267
+ def list
268
+ response = http_get("/prompts")
269
+ return [] unless response.code == '200'
270
+
271
+ JSON.parse(response.body)['prompt_ids']
272
+ end
273
+
274
+ private
275
+
276
+ def http_get(path)
277
+ uri = URI("#{@base_url}#{path}")
278
+ http = Net::HTTP.new(uri.host, uri.port)
279
+ http.use_ssl = uri.scheme == 'https'
280
+
281
+ request = Net::HTTP::Get.new(uri)
282
+ add_auth_header(request)
283
+
284
+ http.request(request)
285
+ end
286
+
287
+ def http_post(path, body)
288
+ uri = URI("#{@base_url}#{path}")
289
+ http = Net::HTTP.new(uri.host, uri.port)
290
+ http.use_ssl = uri.scheme == 'https'
291
+
292
+ request = Net::HTTP::Post.new(uri)
293
+ request['Content-Type'] = 'application/json'
294
+ request.body = body
295
+ add_auth_header(request)
296
+
297
+ http.request(request)
298
+ end
299
+
300
+ def add_auth_header(request)
301
+ return unless @api_token
302
+ request['Authorization'] = "Bearer #{@api_token}"
303
+ end
304
+ end
305
+ ```
306
+
307
+ ## Adapter Registration
308
+
309
+ Register your custom adapter:
310
+
311
+ ```ruby
312
+ # Global configuration
313
+ PromptManager.configure do |config|
314
+ config.storage = CustomAdapter.new(option: 'value')
315
+ end
316
+
317
+ # Per-prompt configuration
318
+ prompt = PromptManager::Prompt.new(
319
+ id: 'special_prompt',
320
+ storage: CustomAdapter.new
321
+ )
322
+ ```
323
+
324
+ ## Error Handling
325
+
326
+ ### Standard Exceptions
327
+
328
+ All adapters should raise these standard exceptions:
329
+
330
+ ```ruby
331
+ # Prompt not found
332
+ raise PromptManager::PromptNotFoundError.new("Prompt 'xyz' not found")
333
+
334
+ # Storage operation failed
335
+ raise PromptManager::StorageError.new("Connection timeout")
336
+
337
+ # Configuration error
338
+ raise PromptManager::ConfigurationError.new("Invalid database URL")
339
+ ```
340
+
341
+ ### Error Context
342
+
343
+ Provide context in error messages:
344
+
345
+ ```ruby
346
+ begin
347
+ content = storage.read(prompt_id)
348
+ rescue => e
349
+ raise PromptManager::StorageError.new(
350
+ "Failed to read prompt '#{prompt_id}': #{e.message}"
351
+ )
352
+ end
353
+ ```
354
+
355
+ ## Performance Considerations
356
+
357
+ ### Connection Pooling
358
+
359
+ ```ruby
360
+ class PooledAdapter < PromptManager::Storage::Base
361
+ def initialize(pool_size: 10, **options)
362
+ super(**options)
363
+ @pool = ConnectionPool.new(size: pool_size) do
364
+ create_connection
365
+ end
366
+ end
367
+
368
+ def read(prompt_id)
369
+ @pool.with { |conn| conn.read(prompt_id) }
370
+ end
371
+ end
372
+ ```
373
+
374
+ ### Caching
375
+
376
+ ```ruby
377
+ class CachedAdapter < PromptManager::Storage::Base
378
+ def initialize(cache_ttl: 300, **options)
379
+ super(**options)
380
+ @cache = {}
381
+ @cache_ttl = cache_ttl
382
+ end
383
+
384
+ def read(prompt_id)
385
+ cached = @cache[prompt_id]
386
+ if cached && (Time.current - cached[:timestamp]) < @cache_ttl
387
+ return cached[:content]
388
+ end
389
+
390
+ content = super(prompt_id)
391
+ @cache[prompt_id] = {
392
+ content: content,
393
+ timestamp: Time.current
394
+ }
395
+ content
396
+ end
397
+ end
398
+ ```
399
+
400
+ ## Testing Adapters
401
+
402
+ ### RSpec Shared Examples
403
+
404
+ ```ruby
405
+ # spec/support/shared_examples/storage_adapter.rb
406
+ RSpec.shared_examples 'a storage adapter' do
407
+ let(:prompt_id) { 'test_prompt' }
408
+ let(:content) { 'Hello [NAME]!' }
409
+
410
+ describe '#write and #read' do
411
+ it 'stores and retrieves content' do
412
+ expect(adapter.write(prompt_id, content)).to be true
413
+ expect(adapter.read(prompt_id)).to eq content
414
+ end
415
+ end
416
+
417
+ describe '#exist?' do
418
+ it 'returns false for non-existent prompts' do
419
+ expect(adapter.exist?('non_existent')).to be false
420
+ end
421
+
422
+ it 'returns true for existing prompts' do
423
+ adapter.write(prompt_id, content)
424
+ expect(adapter.exist?(prompt_id)).to be true
425
+ end
426
+ end
427
+
428
+ describe '#delete' do
429
+ it 'removes prompts' do
430
+ adapter.write(prompt_id, content)
431
+ expect(adapter.delete(prompt_id)).to be true
432
+ expect(adapter.exist?(prompt_id)).to be false
433
+ end
434
+ end
435
+
436
+ describe '#list' do
437
+ it 'returns all prompt IDs' do
438
+ adapter.write('prompt1', 'content1')
439
+ adapter.write('prompt2', 'content2')
440
+
441
+ expect(adapter.list).to contain_exactly('prompt1', 'prompt2')
442
+ end
443
+ end
444
+ end
445
+
446
+ # Usage in adapter specs
447
+ describe CustomAdapter do
448
+ let(:adapter) { described_class.new(options) }
449
+
450
+ include_examples 'a storage adapter'
451
+ end
452
+ ```
453
+
454
+ ## Best Practices
455
+
456
+ 1. **Thread Safety**: Ensure adapter operations are thread-safe
457
+ 2. **Error Handling**: Use standard PromptManager exceptions
458
+ 3. **Resource Management**: Properly close connections and clean up resources
459
+ 4. **Configuration Validation**: Validate configuration parameters in constructor
460
+ 5. **Documentation**: Document all configuration options and behavior
461
+ 6. **Testing**: Use shared examples to ensure consistent behavior
462
+ 7. **Performance**: Consider caching and connection pooling for remote storage
@@ -0,0 +1 @@
1
+ data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A4uLiDOHh4Rjh4eEY4eHhGOHh4Rjh4eEY4eHhGOHh4Rji4uIM////AP///wD///8A////AP///wDY2NgspqamjJmZmbeZmZm3mZmZt5mZmbeZmZm3mZmZt5mZmbeZmZm3pqamjNjY2Cz///8A////AP///wCfn5+MZGRk/1FRUX9RUVF/UVFRX1FRUX9RUVF/UVFRX1FRUX9RUVF/UVFRX2RkZP+fn5+M////AP///wCWlpa3UFBQ/4CAgP+BgYH/gYGB/4GBgf+BgYH/gYGB/4GBgf+BgYH/gYGB/4CAgP9QUFD/lpaWt////wCWlpa3UFBQ/4CAgP//////////////////////////////////////////////////////////////////////////////////////gICA/1BQUP+Wlpa3////AJaWlrdQUFD/gICA//////////////////////////////////////////////////7+/v/+/v7//v7+/v+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////X19f/Ozs7/zs7O/87Ozv/Ozs7/9fX1///////////////////////AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////X19f/Ozs7/////////////////zs7O/87Ozv/19fX///////////////////////+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////X19f/Ozs7/zs7O/87Ozv/Ozs7/zs7O/87Ozv/19fX///////////////////////+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////X19f/Ozs7/////////////////zs7O/87Ozv/19fX///////////////////////+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////X19f/Ozs7/zs7O/87Ozv/Ozs7/zs7O/87Ozv/19fX///////////////////////+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////////////////////7+/v/+/v7//v7+/v////////////////////////////////+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID///////////////////////////////////////////////////////////////////////////////////////+AgID/UFBQ/5aWlrf///8AlpaWt1BQUP+AgID/gYGB/4GBgf+BgYH/gYGB/4GBgf+BgYH/gYGB/4GBgf+BgYH/gICA/1BQUP+Wlpa3////AJ+fn4xkZGT/UVFRX1FRUX9RUVF/UVFRX1FRUX9RUVF/UVFRX1FRUX9RUVF/UVFRX2RkZP+fn5+M////AP///wDY2NgspqamjJmZmbeZmZm3mZmZt5mZmbeZmZm3mZmZt5mZmbeZmZm3pqamjNjY2Cz///8A////AP///wD///8A////AP///wDi4uIM4eHhGOHh4Rjh4eEY4eHhGOHh4Rjh4eEY4eHhGOLi4gz///8A////AP///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wA=
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <!-- Background circle -->
4
+ <circle cx="32" cy="32" r="30" fill="#4F46E5" stroke="#3730A3" stroke-width="2"/>
5
+
6
+ <!-- Librarian figure (simplified) -->
7
+ <circle cx="32" cy="22" r="6" fill="#F3F4F6"/>
8
+ <path d="M20 50 Q32 45 44 50" stroke="#F3F4F6" stroke-width="3" fill="none"/>
9
+
10
+ <!-- Floating books -->
11
+ <rect x="12" y="18" width="8" height="6" rx="1" fill="#FBBF24" transform="rotate(-15 16 21)"/>
12
+ <rect x="18" y="12" width="8" height="6" rx="1" fill="#EF4444" transform="rotate(25 22 15)"/>
13
+ <rect x="44" y="16" width="8" height="6" rx="1" fill="#10B981" transform="rotate(15 48 19)"/>
14
+ <rect x="38" y="10" width="8" height="6" rx="1" fill="#8B5CF6" transform="rotate(-25 42 13)"/>
15
+
16
+ <!-- Golden threads (simplified) -->
17
+ <path d="M16 21 Q32 28 48 19" stroke="#FBBF24" stroke-width="1" fill="none" opacity="0.6"/>
18
+ <path d="M22 15 Q32 25 42 13" stroke="#FBBF24" stroke-width="1" fill="none" opacity="0.6"/>
19
+
20
+ <!-- Sparkles -->
21
+ <circle cx="24" cy="35" r="1" fill="#FBBF24"/>
22
+ <circle cx="40" cy="33" r="1" fill="#FBBF24"/>
23
+ <circle cx="28" cy="40" r="1" fill="#FBBF24"/>
24
+ </svg>
@@ -0,0 +1,48 @@
1
+ # Comments and Documentation
2
+
3
+ PromptManager supports comprehensive inline documentation through comments and special sections.
4
+
5
+ ## Line Comments
6
+
7
+ Lines beginning with `#` are treated as comments and ignored during processing:
8
+
9
+ ```text
10
+ # This is a comment describing the prompt
11
+ # Author: Your Name
12
+ # Version: 1.0
13
+
14
+ Hello [NAME]! This text will be processed.
15
+ ```
16
+
17
+ ## Block Comments
18
+
19
+ Everything after `__END__` is ignored, creating a documentation section:
20
+
21
+ ```text
22
+ Your prompt content here...
23
+
24
+ __END__
25
+ This section is completely ignored by PromptManager.
26
+
27
+ Development notes:
28
+ - TODO: Add more parameters
29
+ - Version history
30
+ - Usage examples
31
+ ```
32
+
33
+ ## Documentation Best Practices
34
+
35
+ ```text
36
+ # Description: Customer service greeting template
37
+ # Tags: customer-service, greeting
38
+ # Version: 1.2
39
+ # Author: Support Team
40
+ # Last Updated: 2024-01-15
41
+
42
+ //include common/header.txt
43
+
44
+ Your prompt content...
45
+
46
+ __END__
47
+ Internal notes and documentation go here.
48
+ ```
@@ -0,0 +1,38 @@
1
+ # Directive Processing
2
+
3
+ Directives are special instructions in your prompts that begin with `//` and provide powerful prompt composition capabilities.
4
+
5
+ ## Overview
6
+
7
+ Directives allow you to:
8
+ - Include content from other files
9
+ - Create modular, reusable prompt components
10
+ - Build dynamic prompt structures
11
+ - Process commands during prompt generation
12
+
13
+ ## Built-in Directives
14
+
15
+ ### `//include` (alias: `//import`)
16
+
17
+ Include content from other files:
18
+
19
+ ```text
20
+ //include common/header.txt
21
+ //import templates/[TEMPLATE_TYPE].txt
22
+
23
+ Your main prompt content here...
24
+ ```
25
+
26
+ ## Example
27
+
28
+ ```text title="customer_response.txt"
29
+ //include common/header.txt
30
+
31
+ Dear [CUSTOMER_NAME],
32
+
33
+ Thank you for your inquiry about [TOPIC].
34
+
35
+ //include common/footer.txt
36
+ ```
37
+
38
+ For detailed examples and advanced usage, see the [Basic Examples](../examples/basic.md).
@@ -0,0 +1,68 @@
1
+ # ERB Integration
2
+
3
+ PromptManager supports ERB (Embedded Ruby) templating for dynamic content generation.
4
+
5
+ ## Enabling ERB
6
+
7
+ ```ruby
8
+ prompt = PromptManager::Prompt.new(
9
+ id: 'dynamic_prompt',
10
+ erb_flag: true
11
+ )
12
+ ```
13
+
14
+ ## Basic Usage
15
+
16
+ ```text title="dynamic_prompt.txt"
17
+ Current date: <%= Date.today.strftime('%B %d, %Y') %>
18
+
19
+ <% if '[PRIORITY]' == 'high' %>
20
+ 🚨 URGENT: This requires immediate attention!
21
+ <% else %>
22
+ 📋 Standard processing request.
23
+ <% end %>
24
+
25
+ Generated at: <%= Time.now %>
26
+ ```
27
+
28
+ ## Advanced Examples
29
+
30
+ ### System Information Template
31
+
32
+ ```text
33
+ **Timestamp**: <%= Time.now.strftime('%A, %B %d, %Y at %I:%M:%S %p %Z') %>
34
+ **Analysis Duration**: <%= Time.now - Time.parse('2024-01-01') %> seconds since 2024 began
35
+
36
+ <% if RUBY_PLATFORM.include?('darwin') %>
37
+ **Platform**: macOS/Darwin System
38
+ **Ruby Platform**: <%= RUBY_PLATFORM %>
39
+ **Ruby Version**: <%= RUBY_VERSION %>
40
+ **Ruby Engine**: <%= RUBY_ENGINE %>
41
+ <% elsif RUBY_PLATFORM.include?('linux') %>
42
+ **Platform**: Linux System
43
+ **Ruby Platform**: <%= RUBY_PLATFORM %>
44
+ **Ruby Version**: <%= RUBY_VERSION %>
45
+ **Ruby Engine**: <%= RUBY_ENGINE %>
46
+ <% else %>
47
+ **Platform**: Other Unix-like System
48
+ **Ruby Platform**: <%= RUBY_PLATFORM %>
49
+ **Ruby Version**: <%= RUBY_VERSION %>
50
+ **Ruby Engine**: <%= RUBY_ENGINE %>
51
+ <% end %>
52
+
53
+ **Performance Context**: <%= `uptime`.strip rescue 'Unable to determine' %>
54
+ ```
55
+
56
+ ### Complete Integration Example
57
+
58
+ See the complete [advanced_integrations.rb](https://github.com/MadBomber/prompt_manager/blob/main/examples/advanced_integrations.rb) example that demonstrates:
59
+
60
+ - ERB templating with system information
61
+ - Dynamic timestamp generation
62
+ - Platform-specific content rendering
63
+ - Integration with OpenAI API streaming
64
+ - Professional UI with `tty-spinner`
65
+
66
+ This example shows how to create sophisticated prompts that adapt to your system environment and generate technical analysis reports.
67
+
68
+ For more comprehensive ERB examples, see the [Examples documentation](../examples.md).