ruby_llm 1.0.1 → 1.1.0rc1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +28 -12
  3. data/lib/ruby_llm/active_record/acts_as.rb +46 -7
  4. data/lib/ruby_llm/aliases.json +65 -0
  5. data/lib/ruby_llm/aliases.rb +56 -0
  6. data/lib/ruby_llm/chat.rb +10 -9
  7. data/lib/ruby_llm/configuration.rb +4 -0
  8. data/lib/ruby_llm/error.rb +15 -4
  9. data/lib/ruby_llm/models.json +1163 -303
  10. data/lib/ruby_llm/models.rb +40 -11
  11. data/lib/ruby_llm/provider.rb +32 -39
  12. data/lib/ruby_llm/providers/anthropic/capabilities.rb +8 -9
  13. data/lib/ruby_llm/providers/anthropic/chat.rb +31 -4
  14. data/lib/ruby_llm/providers/anthropic/streaming.rb +12 -6
  15. data/lib/ruby_llm/providers/anthropic.rb +4 -0
  16. data/lib/ruby_llm/providers/bedrock/capabilities.rb +168 -0
  17. data/lib/ruby_llm/providers/bedrock/chat.rb +108 -0
  18. data/lib/ruby_llm/providers/bedrock/models.rb +84 -0
  19. data/lib/ruby_llm/providers/bedrock/signing.rb +831 -0
  20. data/lib/ruby_llm/providers/bedrock/streaming/base.rb +46 -0
  21. data/lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb +63 -0
  22. data/lib/ruby_llm/providers/bedrock/streaming/message_processing.rb +79 -0
  23. data/lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb +90 -0
  24. data/lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb +91 -0
  25. data/lib/ruby_llm/providers/bedrock/streaming.rb +36 -0
  26. data/lib/ruby_llm/providers/bedrock.rb +83 -0
  27. data/lib/ruby_llm/providers/deepseek/chat.rb +17 -0
  28. data/lib/ruby_llm/providers/deepseek.rb +5 -0
  29. data/lib/ruby_llm/providers/gemini/capabilities.rb +50 -34
  30. data/lib/ruby_llm/providers/gemini/chat.rb +8 -15
  31. data/lib/ruby_llm/providers/gemini/images.rb +5 -10
  32. data/lib/ruby_llm/providers/gemini/streaming.rb +35 -76
  33. data/lib/ruby_llm/providers/gemini/tools.rb +12 -12
  34. data/lib/ruby_llm/providers/gemini.rb +4 -0
  35. data/lib/ruby_llm/providers/openai/capabilities.rb +146 -206
  36. data/lib/ruby_llm/providers/openai/streaming.rb +9 -13
  37. data/lib/ruby_llm/providers/openai.rb +4 -0
  38. data/lib/ruby_llm/streaming.rb +96 -0
  39. data/lib/ruby_llm/version.rb +1 -1
  40. data/lib/ruby_llm.rb +6 -3
  41. data/lib/tasks/browser_helper.rb +97 -0
  42. data/lib/tasks/capability_generator.rb +123 -0
  43. data/lib/tasks/capability_scraper.rb +224 -0
  44. data/lib/tasks/cli_helper.rb +22 -0
  45. data/lib/tasks/code_validator.rb +29 -0
  46. data/lib/tasks/model_updater.rb +66 -0
  47. data/lib/tasks/models.rake +28 -193
  48. data/lib/tasks/vcr.rake +13 -30
  49. metadata +27 -19
  50. data/.github/workflows/cicd.yml +0 -158
  51. data/.github/workflows/docs.yml +0 -53
  52. data/.gitignore +0 -59
  53. data/.overcommit.yml +0 -26
  54. data/.rspec +0 -3
  55. data/.rubocop.yml +0 -10
  56. data/.yardopts +0 -12
  57. data/CONTRIBUTING.md +0 -207
  58. data/Gemfile +0 -33
  59. data/Rakefile +0 -9
  60. data/bin/console +0 -17
  61. data/bin/setup +0 -6
  62. data/ruby_llm.gemspec +0 -44
@@ -1,208 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'English'
4
- require 'faraday'
5
- require 'fileutils'
6
- require 'nokogiri'
7
- require 'ruby_llm'
8
-
9
- # URLs to process
10
- PROVIDER_DOCS = {
11
- openai: {
12
- models: 'https://platform.openai.com/docs/models',
13
- pricing: 'https://platform.openai.com/docs/pricing'
14
- },
15
- gemini: {
16
- models: 'https://ai.google.dev/gemini-api/docs/models/gemini',
17
- pricing: 'https://ai.google.dev/gemini-api/docs/pricing'
18
- },
19
- deepseek: {
20
- models: 'https://api-docs.deepseek.com/quick_start/pricing/'
21
- },
22
- anthropic: {
23
- models: 'https://docs.anthropic.com/en/docs/about-claude/models/all-models'
24
- }
25
- }.freeze
26
-
27
- def fetch_page(url) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
28
- if url.include?('openai.com')
29
- puts "Please visit #{url} and paste the content below (type 'END' on a new line when done):"
30
- original_separator = $INPUT_RECORD_SEPARATOR
31
- $/ = 'END'
32
- content = $stdin.gets&.chomp
33
- $/ = original_separator
34
-
35
- raise "No content provided for #{url}" unless content
36
-
37
- content
38
- else
39
- response = http_client.get(url)
40
- html = Nokogiri::HTML(response.body)
41
-
42
- # Remove script tags and comments
43
- html.css('script').remove
44
- html.xpath('//comment()').remove
45
-
46
- # Extract text content
47
- text = html.css('body').text
48
-
49
- # Clean up whitespace
50
- text.gsub!(/\s+/, ' ')
51
- text.strip!
52
-
53
- text
54
- end
55
- rescue StandardError => e
56
- raise "Failed to fetch #{url}: #{e.message}"
57
- end
58
-
59
- def http_client
60
- @http_client ||= Faraday.new do |f|
61
- f.response :raise_error
62
- f.response :logger, RubyLLM.logger, { headers: false, bodies: true }
63
- end
64
- end
3
+ require_relative 'model_updater'
4
+ require_relative 'capability_scraper'
5
+ require_relative 'capability_generator'
65
6
 
66
7
  namespace :models do # rubocop:disable Metrics/BlockLength
67
- desc 'Update available models from providers'
8
+ desc 'Update available models from providers (API keys needed)'
68
9
  task :update do
69
- # Configure API keys
70
- RubyLLM.configure do |config|
71
- config.openai_api_key = ENV.fetch('OPENAI_API_KEY')
72
- config.anthropic_api_key = ENV.fetch('ANTHROPIC_API_KEY')
73
- config.gemini_api_key = ENV.fetch('GEMINI_API_KEY')
74
- config.deepseek_api_key = ENV.fetch('DEEPSEEK_API_KEY')
75
- end
76
-
77
- models = RubyLLM.models.refresh!
78
- models.save_models
79
-
80
- puts "Updated models.json with #{models.all.size} models:"
81
- RubyLLM::Provider.providers.each do |provider_sym, provider_module|
82
- provider_name = provider_module.to_s.split('::').last
83
- provider_models = models.all.select { |m| m.provider == provider_sym.to_s }
84
- puts "#{provider_name} models: #{provider_models.size}"
85
- end
10
+ ModelUpdater.new.run
86
11
  end
87
12
 
88
- desc 'Update model capabilities modules by scraping provider documentation (use PROVIDER=name to update only one)'
89
- task :update_capabilities do # rubocop:disable Metrics/BlockLength
90
- # Check if a specific provider was requested
91
- target_provider = ENV['PROVIDER']&.to_sym
92
-
93
- # Configure API keys
94
- RubyLLM.configure do |config|
95
- config.openai_api_key = ENV.fetch('OPENAI_API_KEY')
96
- config.anthropic_api_key = ENV.fetch('ANTHROPIC_API_KEY')
97
- config.gemini_api_key = ENV.fetch('GEMINI_API_KEY')
13
+ desc 'Update capabilities modules (GEMINI_API_KEY needed)'
14
+ task :update_capabilities, [:providers] do |_t, args|
15
+ gemini_key = ENV.fetch('GEMINI_API_KEY', nil)
16
+ unless gemini_key && !gemini_key.empty?
17
+ puts 'Error: GEMINI_API_KEY required'
18
+ exit(1)
98
19
  end
99
20
 
100
- # Filter providers if a specific one was requested
101
- providers_to_process = if target_provider && PROVIDER_DOCS.key?(target_provider)
102
- { target_provider => PROVIDER_DOCS[target_provider] }
103
- else
104
- PROVIDER_DOCS
105
- end
106
-
107
- # Process each provider
108
- providers_to_process.each do |provider, urls| # rubocop:disable Metrics/BlockLength
109
- puts "Processing #{provider}..."
110
-
111
- # Initialize our AI assistants
112
- #
113
- gemini = RubyLLM.chat(model: 'gemini-2.0-flash').with_temperature(0)
114
- claude = RubyLLM.chat(model: 'claude-3-7-sonnet-20250219').with_temperature(0)
115
-
116
- # Read existing capabilities file if present
117
- existing_file = "lib/ruby_llm/providers/#{provider}/capabilities.rb"
118
- existing_code = File.read(existing_file) if File.exist?(existing_file)
119
-
120
- begin
121
- # Download documentation
122
- docs = urls.map do |type, url|
123
- puts " Getting #{type} documentation..."
124
- content = fetch_page(url)
125
-
126
- puts "\nHere's what I got:\n\n"
127
- puts "#{content.slice(0, 500)}...\n\n"
128
-
129
- loop do
130
- print 'Does this content look correct? (y/n): '
131
- answer = $stdin.gets&.chomp&.downcase
132
- break if answer == 'y'
133
- raise "Content verification failed for #{url}" if answer == 'n'
134
- end
135
-
136
- "#{type.to_s.upcase} DOCUMENTATION:\n\n#{content}"
137
- end.join("\n\n")
138
-
139
- # Extract relevant information with Gemini
140
- puts ' Extracting model information...'
141
- extraction_prompt = <<~PROMPT
142
- Extract relevant model capabilities information from this documentation:
143
-
144
- #{docs}
145
-
146
- Focus on:
147
- 1. Available models and their IDs
148
- 2. Context window sizes
149
- 3. Maximum output tokens
150
- 4. Pricing information
151
- 5. Model capabilities (vision, function calling, etc)
152
-
153
- Format the information clearly and concisely, focusing only on facts about the models.
154
- PROMPT
155
-
156
- model_info = gemini.ask(extraction_prompt).content
157
-
158
- # Generate Ruby code with Claude
159
- puts ' Generating Ruby code...'
160
- code_prompt = <<~PROMPT
161
- I need you to generate a Ruby module for #{provider}'s model capabilities.
162
- Use this extracted model information:
163
-
164
- #{model_info}
165
-
166
- The module should go in lib/ruby_llm/providers/#{provider}/capabilities.rb and follow these conventions:
167
-
168
- 1. Include methods for determining context windows, token limits, pricing, and capabilities
169
- 2. Use consistent naming with other providers
170
- 3. Include detailed pricing information in a PRICES constant
171
- 4. Follow the existing structure in the codebase
172
- 5. Use Ruby idioms and clean code practices
173
- 6. Include module_function to make methods callable at module level
174
- 7. Include all necessary method documentation
175
-
176
- Here's the existing implementation for reference (maintain similar structure and same method names):
177
-
178
- #{existing_code}
179
-
180
- Focus on accuracy and maintaining consistency with the existing codebase structure.
181
- PROMPT
182
-
183
- response = claude.ask(code_prompt)
184
-
185
- # Extract Ruby code from Claude's response
186
- puts " Extracting Ruby code from Claude's response..."
187
- ruby_code = nil
188
-
189
- # Look for Ruby code block
190
- ruby_code = Regexp.last_match(1).strip if response.content =~ /```ruby\s*(.*?)```/m
191
-
192
- # Verify we found Ruby code
193
- raise "No Ruby code block found in Claude's response" if ruby_code.nil? || ruby_code.empty?
21
+ RubyLLM.configure do |c|
22
+ c.gemini_api_key = gemini_key
23
+ c.request_timeout = 300
24
+ end
194
25
 
195
- # Save the file
196
- file_path = "lib/ruby_llm/providers/#{provider}/capabilities.rb"
197
- puts " Writing #{file_path}..."
26
+ target_providers = CapabilityScraper.parse_providers(args[:providers])
198
27
 
199
- FileUtils.mkdir_p(File.dirname(file_path))
200
- File.write(file_path, ruby_code)
201
- rescue StandardError => e
202
- raise "Failed to process #{provider}: #{e.message}"
28
+ begin
29
+ scraper = CapabilityScraper.new(target_providers)
30
+ scraper.run do |provider, docs_html|
31
+ generator = CapabilityGenerator.new(provider, docs_html)
32
+ generator.generate_and_save
203
33
  end
34
+ rescue StandardError => e
35
+ puts "Error: #{e.message}"
36
+ puts e.backtrace.first(5).join("\n")
37
+ ensure
38
+ puts 'Update process complete. Review generated files.'
204
39
  end
205
-
206
- puts "Done! Don't forget to review the generated code and run the tests."
207
40
  end
208
41
  end
42
+
43
+ task default: ['models:update']
data/lib/tasks/vcr.rake CHANGED
@@ -29,13 +29,8 @@ def record_for_providers(providers, cassette_dir) # rubocop:disable Metrics/AbcS
29
29
  return
30
30
  end
31
31
 
32
- # Get URL patterns from the providers themselves
33
- provider_patterns = get_provider_patterns(providers)
34
-
35
- puts "Finding cassettes for providers: #{providers.join(', ')}"
36
-
37
32
  # Find and delete matching cassettes
38
- cassettes_to_delete = find_matching_cassettes(cassette_dir, provider_patterns)
33
+ cassettes_to_delete = find_matching_cassettes(cassette_dir, providers)
39
34
 
40
35
  if cassettes_to_delete.empty?
41
36
  puts 'No cassettes found for the specified providers.'
@@ -51,33 +46,21 @@ def record_for_providers(providers, cassette_dir) # rubocop:disable Metrics/AbcS
51
46
  puts 'Please review the updated cassettes for sensitive information.'
52
47
  end
53
48
 
54
- def get_provider_patterns(providers) # rubocop:disable Metrics/MethodLength
55
- provider_patterns = {}
56
-
57
- providers.each do |provider_name|
58
- provider_module = RubyLLM::Provider.providers[provider_name.to_sym]
59
- next unless provider_module
60
-
61
- # Extract the base URL from the provider's api_base method
62
- api_base = provider_module.api_base.to_s
63
-
64
- # Create a regex pattern from the domain
65
- next unless api_base && !api_base.empty?
66
-
67
- domain = URI.parse(api_base).host
68
- pattern = Regexp.new(Regexp.escape(domain))
69
- provider_patterns[provider_name] = pattern
70
- end
71
-
72
- provider_patterns
73
- end
74
-
75
- def find_matching_cassettes(dir, patterns)
49
+ def find_matching_cassettes(dir, providers) # rubocop:disable Metrics/MethodLength
76
50
  cassettes = []
77
51
 
78
52
  Dir.glob("#{dir}/**/*.yml").each do |file|
79
- content = File.read(file)
80
- cassettes << file if patterns.values.any? { |pattern| content.match?(pattern) }
53
+ basename = File.basename(file)
54
+
55
+ # Precise matching to avoid cross-provider confusion
56
+ providers.each do |provider|
57
+ # Match only exact provider prefixes
58
+ next unless basename =~ /^[^_]*_#{provider}_/ || # For first section like "chat_openai_"
59
+ basename =~ /_#{provider}_[^_]+_/ # For middle sections like "_openai_gpt4_"
60
+
61
+ cassettes << file
62
+ break
63
+ end
81
64
  end
82
65
 
83
66
  cassettes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carmine Paolino
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-23 00:00:00.000000000 Z
11
+ date: 2025-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -96,31 +96,21 @@ dependencies:
96
96
  version: '2'
97
97
  description: A delightful Ruby way to work with AI. Chat in text, analyze and generate
98
98
  images, understand audio, and use tools through a unified interface to OpenAI, Anthropic,
99
- Google, and DeepSeek. Built for developer happiness with automatic token counting,
100
- proper streaming, and Rails integration. No wrapping your head around multiple APIs
101
- - just clean Ruby code that works.
99
+ Google, AWS Bedrock Anthropic, and DeepSeek. Built for developer happiness with
100
+ automatic token counting, proper streaming, and Rails integration. No wrapping your
101
+ head around multiple APIs - just clean Ruby code that works.
102
102
  email:
103
103
  - carmine@paolino.me
104
104
  executables: []
105
105
  extensions: []
106
106
  extra_rdoc_files: []
107
107
  files:
108
- - ".github/workflows/cicd.yml"
109
- - ".github/workflows/docs.yml"
110
- - ".gitignore"
111
- - ".overcommit.yml"
112
- - ".rspec"
113
- - ".rubocop.yml"
114
- - ".yardopts"
115
- - CONTRIBUTING.md
116
- - Gemfile
117
108
  - LICENSE
118
109
  - README.md
119
- - Rakefile
120
- - bin/console
121
- - bin/setup
122
110
  - lib/ruby_llm.rb
123
111
  - lib/ruby_llm/active_record/acts_as.rb
112
+ - lib/ruby_llm/aliases.json
113
+ - lib/ruby_llm/aliases.rb
124
114
  - lib/ruby_llm/chat.rb
125
115
  - lib/ruby_llm/chunk.rb
126
116
  - lib/ruby_llm/configuration.rb
@@ -141,8 +131,20 @@ files:
141
131
  - lib/ruby_llm/providers/anthropic/models.rb
142
132
  - lib/ruby_llm/providers/anthropic/streaming.rb
143
133
  - lib/ruby_llm/providers/anthropic/tools.rb
134
+ - lib/ruby_llm/providers/bedrock.rb
135
+ - lib/ruby_llm/providers/bedrock/capabilities.rb
136
+ - lib/ruby_llm/providers/bedrock/chat.rb
137
+ - lib/ruby_llm/providers/bedrock/models.rb
138
+ - lib/ruby_llm/providers/bedrock/signing.rb
139
+ - lib/ruby_llm/providers/bedrock/streaming.rb
140
+ - lib/ruby_llm/providers/bedrock/streaming/base.rb
141
+ - lib/ruby_llm/providers/bedrock/streaming/content_extraction.rb
142
+ - lib/ruby_llm/providers/bedrock/streaming/message_processing.rb
143
+ - lib/ruby_llm/providers/bedrock/streaming/payload_processing.rb
144
+ - lib/ruby_llm/providers/bedrock/streaming/prelude_handling.rb
144
145
  - lib/ruby_llm/providers/deepseek.rb
145
146
  - lib/ruby_llm/providers/deepseek/capabilities.rb
147
+ - lib/ruby_llm/providers/deepseek/chat.rb
146
148
  - lib/ruby_llm/providers/gemini.rb
147
149
  - lib/ruby_llm/providers/gemini/capabilities.rb
148
150
  - lib/ruby_llm/providers/gemini/chat.rb
@@ -163,12 +165,18 @@ files:
163
165
  - lib/ruby_llm/providers/openai/tools.rb
164
166
  - lib/ruby_llm/railtie.rb
165
167
  - lib/ruby_llm/stream_accumulator.rb
168
+ - lib/ruby_llm/streaming.rb
166
169
  - lib/ruby_llm/tool.rb
167
170
  - lib/ruby_llm/tool_call.rb
168
171
  - lib/ruby_llm/version.rb
172
+ - lib/tasks/browser_helper.rb
173
+ - lib/tasks/capability_generator.rb
174
+ - lib/tasks/capability_scraper.rb
175
+ - lib/tasks/cli_helper.rb
176
+ - lib/tasks/code_validator.rb
177
+ - lib/tasks/model_updater.rb
169
178
  - lib/tasks/models.rake
170
179
  - lib/tasks/vcr.rake
171
- - ruby_llm.gemspec
172
180
  homepage: https://rubyllm.com
173
181
  licenses:
174
182
  - MIT
@@ -1,158 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [ "main" ]
6
- paths:
7
- - 'lib/**'
8
- - 'spec/**'
9
- - 'Gemfile'
10
- - 'Rakefile'
11
- - 'ruby_llm.gemspec'
12
- - '.github/workflows/cicd.yml'
13
- pull_request:
14
- branches: [ "main" ]
15
- paths:
16
- - 'lib/**'
17
- - 'spec/**'
18
- - 'Gemfile'
19
- - 'Rakefile'
20
- - 'ruby_llm.gemspec'
21
- - '.github/workflows/cicd.yml'
22
- workflow_call:
23
-
24
- # Define default permissions for this workflow
25
- permissions:
26
- contents: read
27
- packages: write # Needed for publishing to GitHub Packages
28
-
29
- jobs:
30
- test:
31
- runs-on: ubuntu-latest
32
- strategy:
33
- matrix:
34
- ruby-version: ['3.1']
35
-
36
- steps:
37
- - uses: actions/checkout@v4
38
-
39
- - name: Set up Ruby
40
- uses: ruby/setup-ruby@v1
41
- with:
42
- ruby-version: ${{ matrix.ruby-version }}
43
- bundler-cache: true
44
-
45
- - name: Install dependencies
46
- run: bundle install
47
-
48
- - name: Check code format
49
- run: bundle exec rubocop
50
-
51
- - name: Run tests
52
- env:
53
- # For PRs, we use VCR cassettes
54
- # For main branch, we use real API keys for verification
55
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
56
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
57
- GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
58
- DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
59
- run: bundle exec rspec
60
-
61
- - name: Upload coverage to Codecov
62
- uses: codecov/codecov-action@v5
63
- env:
64
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
65
- with:
66
- files: ./coverage/coverage.xml
67
- fail_ci_if_error: false
68
-
69
- publish:
70
- name: Build + Publish
71
- needs: test
72
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
73
- runs-on: ubuntu-latest
74
- permissions:
75
- contents: read
76
- packages: write
77
-
78
- steps:
79
- - uses: actions/checkout@v4
80
-
81
- - name: Set up Ruby
82
- uses: ruby/setup-ruby@v1
83
- with:
84
- ruby-version: '3.3'
85
- bundler-cache: true
86
-
87
- - name: Check if version has changed
88
- id: check_version
89
- run: |
90
- VERSION=$(ruby -r ./lib/ruby_llm/version.rb -e "puts RubyLLM::VERSION")
91
- echo "Current version: $VERSION"
92
-
93
- # Try to fetch from RubyGems
94
- PUBLISHED_VERSION=$(gem list ruby_llm -r | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' || echo "0.0.0")
95
- echo "Published version: $PUBLISHED_VERSION"
96
-
97
- if [ "$VERSION" = "$PUBLISHED_VERSION" ]; then
98
- echo "Version has not changed, skipping publish"
99
- echo "version_changed=false" >> $GITHUB_OUTPUT
100
- else
101
- echo "Version has changed from $PUBLISHED_VERSION to $VERSION"
102
- echo "version_changed=true" >> $GITHUB_OUTPUT
103
- fi
104
-
105
- - name: Test with real APIs before publishing
106
- if: steps.check_version.outputs.version_changed == 'true'
107
- run: |
108
- echo "Removing all VCR cassettes to test against real APIs..."
109
- rm -rf spec/fixtures/vcr_cassettes
110
-
111
- echo "Running tests with real API calls..."
112
- env -u CI bundle exec rspec
113
- env:
114
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
115
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
116
- GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
117
- DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
118
-
119
- - name: Publish to GPR
120
- if: steps.check_version.outputs.version_changed == 'true'
121
- run: |
122
- mkdir -p $HOME/.gem
123
- touch $HOME/.gem/credentials
124
- chmod 0600 $HOME/.gem/credentials
125
- printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
126
- gem build *.gemspec
127
- output=$(gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem 2>&1) || {
128
- echo "$output"
129
- if echo "$output" | grep -q "already been pushed"; then
130
- echo "Version already exists, skipping"
131
- exit 0
132
- else
133
- exit 1
134
- fi
135
- }
136
- env:
137
- GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
138
- OWNER: ${{ github.repository_owner }}
139
-
140
- - name: Publish to RubyGems
141
- if: steps.check_version.outputs.version_changed == 'true'
142
- run: |
143
- mkdir -p $HOME/.gem
144
- touch $HOME/.gem/credentials
145
- chmod 0600 $HOME/.gem/credentials
146
- printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
147
- gem build *.gemspec
148
- output=$(gem push *.gem 2>&1) || {
149
- echo "$output"
150
- if echo "$output" | grep -q "Repushing of gem versions is not allowed"; then
151
- echo "Version already exists, skipping"
152
- exit 0
153
- else
154
- exit 1
155
- fi
156
- }
157
- env:
158
- GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -1,53 +0,0 @@
1
- name: Deploy docs
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- paths:
7
- - 'docs/**'
8
- - '.github/workflows/docs.yml'
9
- workflow_dispatch:
10
-
11
- permissions:
12
- contents: read
13
- pages: write
14
- id-token: write
15
-
16
- concurrency:
17
- group: "pages"
18
- cancel-in-progress: false
19
-
20
- jobs:
21
- build:
22
- runs-on: ubuntu-latest
23
- steps:
24
- - name: Checkout
25
- uses: actions/checkout@v4
26
- - name: Setup Ruby
27
- uses: ruby/setup-ruby@v1
28
- with:
29
- ruby-version: '3.3'
30
- bundler-cache: true
31
- working-directory: docs
32
- - name: Setup Pages
33
- uses: actions/configure-pages@v4
34
- - name: Build with Jekyll
35
- working-directory: docs
36
- run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
37
- env:
38
- JEKYLL_ENV: production
39
- - name: Upload artifact
40
- uses: actions/upload-pages-artifact@v3
41
- with:
42
- path: docs/_site
43
-
44
- deploy:
45
- environment:
46
- name: github-pages
47
- url: ${{ steps.deployment.outputs.page_url }}
48
- runs-on: ubuntu-latest
49
- needs: build
50
- steps:
51
- - name: Deploy to GitHub Pages
52
- id: deployment
53
- uses: actions/deploy-pages@v4
data/.gitignore DELETED
@@ -1,59 +0,0 @@
1
- *.gem
2
- *.rbc
3
- /.config
4
- /coverage/
5
- /InstalledFiles
6
- /pkg/
7
- /spec/reports/
8
- /spec/examples.txt
9
- /test/tmp/
10
- /test/version_tmp/
11
- /tmp/
12
- .rspec_status
13
-
14
- # Used by dotenv library to load environment variables.
15
- .env
16
-
17
- # Ignore Byebug command history file.
18
- .byebug_history
19
-
20
- ## Specific to RubyMotion:
21
- .dat*
22
- .repl_history
23
- build/
24
- *.bridgesupport
25
- build-iPhoneOS/
26
- build-iPhoneSimulator/
27
-
28
- ## Specific to RubyMotion (use of CocoaPods):
29
- #
30
- # We recommend against adding the Pods directory to your .gitignore. However
31
- # you should judge for yourself, the pros and cons are mentioned at:
32
- # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
33
- #
34
- # vendor/Pods/
35
-
36
- ## Documentation cache and generated files:
37
- /.yardoc/
38
- /_yardoc/
39
- /doc/
40
- /rdoc/
41
-
42
- ## Environment normalization:
43
- /.bundle/
44
- /vendor/bundle
45
- /lib/bundler/man/
46
-
47
- # for a library or gem, you might want to ignore these files since the code is
48
- # intended to run in multiple environments; otherwise, check them in:
49
- Gemfile.lock
50
- # .ruby-version
51
- # .ruby-gemset
52
-
53
- # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
54
- .rvmrc
55
-
56
- # Used by RuboCop. Remote config files pulled in from inherit_from directive.
57
- # .rubocop-https?--*
58
-
59
- repomix-output.*
data/.overcommit.yml DELETED
@@ -1,26 +0,0 @@
1
- PreCommit:
2
- RuboCop:
3
- enabled: true
4
- auto_correct: true
5
- on_warn: fail # Treat all warnings as failures
6
-
7
- Flay:
8
- enabled: true
9
-
10
- RSpec:
11
- enabled: true
12
- command: ['bundle', 'exec', 'rspec']
13
- on_warn: fail
14
-
15
- TrailingWhitespace:
16
- enabled: true
17
- auto_correct: true
18
- exclude:
19
- - '**/db/structure.sql' # Ignore trailing whitespace in generated files
20
-
21
- PostCheckout:
22
- ALL: # Special hook name that customizes all hooks of this type
23
- quiet: true # Change all post-checkout hooks to only display output on failure
24
-
25
- IndexTags:
26
- enabled: true # Generate a tags file with `ctags` each time HEAD changes
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --require spec_helper
2
- --format documentation
3
- --color