promptly 0.1.7 → 0.1.17

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,116 @@
1
+ ## Quick Start
2
+
3
+ ### 1. Create prompt templates
4
+
5
+ Create `app/prompts/user_onboarding/welcome_email.en.erb`:
6
+
7
+ ```erb
8
+ You are a friendly customer success manager writing a personalized welcome email.
9
+
10
+ Context:
11
+ - User name: <%= name %>
12
+ - App name: <%= app_name %>
13
+ - User's role: <%= user_role %>
14
+ - Available features for this user: <%= features.join(", ") %>
15
+ - User signed up <%= days_since_signup %> days ago
16
+
17
+ Task: Write a warm, personalized welcome email that:
18
+ 1. Addresses the user by name
19
+ 2. Explains the key benefits specific to their role
20
+ 3. Highlights 2-3 most relevant features they should try first
21
+ 4. Includes a clear call-to-action to get started
22
+ 5. Maintains a professional but friendly tone
23
+
24
+ Keep the email concise (under 200 words) and actionable.
25
+ ```
26
+
27
+ Create `app/prompts/user_onboarding/welcome_email.es.erb`:
28
+
29
+ ```erb
30
+ Eres un gerente de éxito del cliente amigable escribiendo un email de bienvenida personalizado.
31
+
32
+ Contexto:
33
+ - Nombre del usuario: <%= name %>
34
+ - Nombre de la app: <%= app_name %>
35
+ - Rol del usuario: <%= user_role %>
36
+ - Funciones disponibles para este usuario: <%= features.join(", ") %>
37
+ - El usuario se registró hace <%= days_since_signup %> días
38
+
39
+ Tarea: Escribe un email de bienvenida cálido y personalizado que:
40
+ 1. Se dirija al usuario por su nombre
41
+ 2. Explique los beneficios clave específicos para su rol
42
+ 3. Destaque 2-3 funciones más relevantes que debería probar primero
43
+ 4. Incluya una llamada a la acción clara para comenzar
44
+ 5. Mantenga un tono profesional pero amigable
45
+
46
+ Mantén el email conciso (menos de 200 palabras) y orientado a la acción.
47
+ ```
48
+
49
+ ### 2. Render in your Rails app
50
+
51
+ ```ruby
52
+ # In a controller, service, or anywhere in Rails
53
+ prompt = Promptly.render(
54
+ "user_onboarding/welcome_email",
55
+ locale: :es,
56
+ locals: {
57
+ name: "María García",
58
+ app_name: "ProjectHub",
59
+ user_role: "Team Lead",
60
+ features: ["Create projects", "Invite team members", "Track progress", "Generate reports"],
61
+ days_since_signup: 2
62
+ }
63
+ )
64
+
65
+ # Send to your AI service (OpenAI, Anthropic, etc.)
66
+ ai_response = openai_client.completions(
67
+ model: "gpt-4",
68
+ messages: [{role: "user", content: prompt}]
69
+ )
70
+
71
+ puts ai_response.dig("choices", 0, "message", "content")
72
+ # => AI-generated personalized welcome email in Spanish
73
+ ```
74
+
75
+ ### 3. Test via Rails console
76
+
77
+ ```ruby
78
+ rails console
79
+
80
+ # Render the prompt before sending to AI
81
+ prompt = Promptly.render(
82
+ "user_onboarding/welcome_email",
83
+ locale: :en,
84
+ locals: {
85
+ name: "John Smith",
86
+ app_name: "ProjectHub",
87
+ user_role: "Developer",
88
+ features: ["API access", "Code reviews", "Deployment tools"],
89
+ days_since_signup: 1
90
+ }
91
+ )
92
+ puts prompt
93
+
94
+ # Uses I18n.locale by default
95
+ I18n.locale = :es
96
+ prompt = Promptly.render(
97
+ "user_onboarding/welcome_email",
98
+ locals: {
99
+ name: "María García",
100
+ app_name: "ProjectHub",
101
+ user_role: "Team Lead",
102
+ features: ["Crear proyectos", "Invitar miembros", "Seguimiento"],
103
+ days_since_signup: 3
104
+ }
105
+ )
106
+ ```
107
+
108
+ ### 4. CLI rendering
109
+
110
+ ```bash
111
+ # Render specific locale (shows the prompt, not AI output)
112
+ rails ai_prompts:render[user_onboarding/welcome_email,es]
113
+
114
+ # Uses default locale
115
+ rails ai_prompts:render[user_onboarding/welcome_email]
116
+ ```
@@ -0,0 +1,116 @@
1
+ ## Rails App Integration
2
+
3
+ ### Service Object Pattern
4
+
5
+ ```ruby
6
+ # app/services/ai_prompt_service.rb
7
+ class AiPromptService
8
+ def self.generate_welcome_email(user, locale: I18n.locale)
9
+ prompt = Promptly.render(
10
+ "user_onboarding/welcome_email",
11
+ locale: locale,
12
+ locals: {
13
+ name: user.full_name,
14
+ app_name: Rails.application.class.module_parent_name,
15
+ user_role: user.role.humanize,
16
+ features: available_features_for(user),
17
+ days_since_signup: (Date.current - user.created_at.to_date).to_i
18
+ }
19
+ )
20
+
21
+ # Send to AI service and return generated content
22
+ openai_client.chat(
23
+ model: "gpt-4",
24
+ messages: [{role: "user", content: prompt}]
25
+ ).dig("choices", 0, "message", "content")
26
+ end
27
+
28
+ private
29
+
30
+ def self.available_features_for(user)
31
+ # Return features based on user's plan, role, etc.
32
+ case user.plan
33
+ when "basic"
34
+ ["Create projects", "Basic reporting"]
35
+ when "pro"
36
+ ["Create projects", "Team collaboration", "Advanced analytics", "API access"]
37
+ else
38
+ ["Create projects"]
39
+ end
40
+ end
41
+
42
+ def self.openai_client
43
+ @openai_client ||= OpenAI::Client.new(access_token: Rails.application.credentials.openai_api_key)
44
+ end
45
+ end
46
+ ```
47
+
48
+ ### Mailer Integration
49
+
50
+ ```ruby
51
+ # app/mailers/user_mailer.rb
52
+ class UserMailer < ApplicationMailer
53
+ def welcome_email(user)
54
+ @user = user
55
+ @ai_content = AiPromptService.generate_welcome_email(user, locale: user.locale)
56
+
57
+ mail(
58
+ to: user.email,
59
+ subject: t('mailer.welcome.subject')
60
+ )
61
+ end
62
+ end
63
+ ```
64
+
65
+ ### Background Job Usage
66
+
67
+ ```ruby
68
+ # app/jobs/generate_ai_content_job.rb
69
+ class GenerateAiContentJob < ApplicationJob
70
+ def perform(user_id, prompt_identifier, locals = {})
71
+ user = User.find(user_id)
72
+
73
+ prompt = Promptly.render(
74
+ prompt_identifier,
75
+ locale: user.locale,
76
+ locals: locals.merge(
77
+ user_name: user.full_name,
78
+ user_role: user.role,
79
+ account_type: user.account_type
80
+ )
81
+ )
82
+
83
+ # Generate AI content
84
+ ai_response = openai_client.chat(
85
+ model: "gpt-4",
86
+ messages: [{role: "user", content: prompt}]
87
+ )
88
+
89
+ generated_content = ai_response.dig("choices", 0, "message", "content")
90
+
91
+ # Store or send the generated content
92
+ user.notifications.create!(
93
+ title: "AI Generated Content Ready",
94
+ content: generated_content,
95
+ notification_type: prompt_identifier.split('/').last
96
+ )
97
+ end
98
+
99
+ private
100
+
101
+ def openai_client
102
+ @openai_client ||= OpenAI::Client.new(access_token: Rails.application.credentials.openai_api_key)
103
+ end
104
+ end
105
+
106
+ # Usage
107
+ GenerateAiContentJob.perform_later(
108
+ user.id,
109
+ "coaching/goal_review",
110
+ {
111
+ current_goals: user.goals.active.pluck(:title),
112
+ progress_summary: "Made good progress on fitness goals",
113
+ challenges: ["Time management", "Consistency"]
114
+ }
115
+ )
116
+ ```
@@ -0,0 +1,27 @@
1
+ ## Schema Validation
2
+
3
+ Ensure all locals passed to templates match a defined schema, so missing or mistyped variables fail fast before sending to AI.
4
+
5
+ ### Schema File Next to Prompt
6
+
7
+ For each prompt, create a `schema.yml` (or `.json`) file alongside the template.
8
+
9
+ **Example:**
10
+
11
+ `app/prompts/user_onboarding/welcome_email.schema.yml`
12
+
13
+ ```yml
14
+ name: string
15
+ app_name: string
16
+ user_role: string
17
+ features: array
18
+ days_since_signup: integer
19
+ ```
20
+
21
+ ### Validation Layer in Promptly
22
+
23
+ The validation is automatically triggered when you call `Promptly.render`. It will check for missing keys and (optionally) value types.
24
+
25
+ Supported types: `string`, `integer`, `array`.
26
+
27
+ If the validation fails, it will raise an `ArgumentError` for missing keys or a `TypeError` for mismatched types.
data/wiki/_Sidebar.md ADDED
@@ -0,0 +1,11 @@
1
+ - [Home](https://github.com/wilburhimself/promptly/wiki)
2
+ - [Quick Start](https://github.com/wilburhimself/promptly/wiki/Quick-Start)
3
+ - [Schema Validation](https://github.com/wilburhimself/promptly/wiki/Schema-Validation)
4
+ - [Helper: render_prompt](https://github.com/wilburhimself/promptly/wiki/Helper-render_prompt)
5
+ - [Rails App Integration](https://github.com/wilburhimself/promptly/wiki/Rails-App-Integration)
6
+ - [I18n Prompts Usage](https://github.com/wilburhimself/promptly/wiki/I18n-Prompts-Usage)
7
+ - [Liquid Templates](https://github.com/wilburhimself/promptly/wiki/Liquid-Templates)
8
+ - [Configuration](https://github.com/wilburhimself/promptly/wiki/Configuration)
9
+ - [Generators](https://github.com/wilburhimself/promptly/wiki/Generators)
10
+ - [Linting Templates](https://github.com/wilburhimself/promptly/wiki/Linting-Templates)
11
+ - [Functional Prompt Tests](https://github.com/wilburhimself/promptly/wiki/Functional-Prompt-Tests)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: promptly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wilbur Suero
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-16 00:00:00.000000000 Z
11
+ date: 2026-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '7.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json_schemer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.3'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +97,7 @@ dependencies:
83
97
  description: Build maintainable, localized, and testable AI prompts using ERB or Liquid
84
98
  templates with Rails conventions
85
99
  email:
86
- - wilbur@example.com
100
+ - suerowilbur@gmail.com
87
101
  executables: []
88
102
  extensions: []
89
103
  extra_rdoc_files: []
@@ -94,15 +108,31 @@ files:
94
108
  - LICENSE
95
109
  - README.md
96
110
  - Rakefile
111
+ - app/prompts/test/prompt.en.erb
112
+ - app/prompts/test/prompt_with_metadata.en.erb
97
113
  - lib/generators/promptly/prompt_generator.rb
98
114
  - lib/promptly.rb
99
115
  - lib/promptly/cache.rb
116
+ - lib/promptly/helper.rb
100
117
  - lib/promptly/locator.rb
101
118
  - lib/promptly/railtie.rb
102
119
  - lib/promptly/renderer.rb
103
120
  - lib/promptly/tasks/ai_prompts.rake
121
+ - lib/promptly/validator.rb
104
122
  - lib/promptly/version.rb
105
- - promptly.gemspec
123
+ - wiki/Configuration.md
124
+ - wiki/Functional-Prompt-Tests.md
125
+ - wiki/Generators.md
126
+ - wiki/Helper-render_prompt.md
127
+ - wiki/Home.md
128
+ - wiki/I18n-Prompts-Usage.md
129
+ - wiki/Linting-Templates.md
130
+ - wiki/Liquid-Templates.md
131
+ - wiki/Prompt-Version-Metadata.md
132
+ - wiki/Quick-Start.md
133
+ - wiki/Rails-App-Integration.md
134
+ - wiki/Schema-Validation.md
135
+ - wiki/_Sidebar.md
106
136
  homepage: https://github.com/wilburhimself/promptly
107
137
  licenses:
108
138
  - MIT
@@ -120,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
150
  requirements:
121
151
  - - ">="
122
152
  - !ruby/object:Gem::Version
123
- version: '3.3'
153
+ version: '3.2'
124
154
  - - "<"
125
155
  - !ruby/object:Gem::Version
126
156
  version: '3.4'
data/promptly.gemspec DELETED
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/promptly/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "promptly"
7
- spec.version = Promptly::VERSION
8
- spec.authors = ["Wilbur Suero"]
9
- spec.email = ["wilbur@example.com"]
10
-
11
- spec.summary = "Opinionated Rails integration for reusable AI prompt templates"
12
- spec.description = "Build maintainable, localized, and testable AI prompts using ERB or Liquid templates with Rails conventions"
13
- spec.homepage = "https://github.com/wilburhimself/promptly"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 3.3", "< 3.4"
16
-
17
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
-
19
- spec.metadata["homepage_uri"] = spec.homepage
20
- spec.metadata["source_code_uri"] = "https://github.com/wilburhimself/promptly"
21
- spec.metadata["changelog_uri"] = "https://github.com/wilburhimself/promptly/blob/main/CHANGELOG.md"
22
- spec.metadata["documentation_uri"] = "https://github.com/wilburhimself/promptly/blob/main/README.md"
23
-
24
- # Specify which files should be added to the gem when it is released.
25
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
- gemfiles = Dir.chdir(__dir__) do
27
- `git ls-files -z`.split("\x0").reject do |f|
28
- (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
29
- end
30
- end
31
- spec.files = gemfiles
32
-
33
- spec.bindir = "exe"
34
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
35
- spec.require_paths = ["lib"]
36
-
37
- # Runtime dependencies (single target: Rails 7.2.x)
38
- spec.add_dependency "actionview", "~> 7.2"
39
-
40
- # Development dependencies
41
- spec.add_development_dependency "rspec", "~> 3.12"
42
- spec.add_development_dependency "standard", "~> 1.37"
43
- spec.add_development_dependency "liquid", "~> 5.5"
44
- # Development dependencies
45
- spec.add_development_dependency "railties", "~> 7.2"
46
- end