agentbill-sdk 1.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2a5d6d3184f1e30d721acd50e8b51ac947d086352bdd4f3f26702adc127b021c
4
+ data.tar.gz: 57eb001ae9a6ba61c002855ad1abbe17fe14fcc3c8fc269b55903b780da669d2
5
+ SHA512:
6
+ metadata.gz: 686aef33e7ff8e70994ffe7ad034beddea13b5adf6fc9cd072288898c253f64c49aae92a28c7068f3de4252304b5b6ed5a86698886a87353ce3912afabb870b2
7
+ data.tar.gz: 2a86b18d8ea9a824fc2de991ae25f7f83473eda13f9ffaa96e6e451d1cca0729fa6cc3d3331e6a292a94e31fb604643b651e23697bbeec96dde6de6cae2d3c1f
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: '[BUG] '
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ **Describe the bug**
10
+ A clear and concise description of what the bug is.
11
+
12
+ **To Reproduce**
13
+ Steps to reproduce the behavior:
14
+ 1. Initialize client with '...'
15
+ 2. Call method '...'
16
+ 3. See error
17
+
18
+ **Expected behavior**
19
+ A clear and concise description of what you expected to happen.
20
+
21
+ **Code Example**
22
+ ```ruby
23
+ # Your code that reproduces the issue
24
+ ```
25
+
26
+ **Environment:**
27
+ - Ruby version: [e.g. 3.2.0]
28
+ - Gem version: [e.g. 1.0.0]
29
+ - OS: [e.g. macOS 13.0]
30
+ - AI Provider: [e.g. OpenAI, Anthropic]
31
+
32
+ **Additional context**
33
+ Add any other context about the problem here.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: '[FEATURE] '
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ **Is your feature request related to a problem? Please describe.**
10
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11
+
12
+ **Describe the solution you'd like**
13
+ A clear and concise description of what you want to happen.
14
+
15
+ **Describe alternatives you've considered**
16
+ A clear and concise description of any alternative solutions or features you've considered.
17
+
18
+ **Use Case**
19
+ Describe how this feature would be used:
20
+ ```ruby
21
+ # Example usage of the proposed feature
22
+ ```
23
+
24
+ **Additional context**
25
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,38 @@
1
+ # Pull Request
2
+
3
+ ## Description
4
+ <!-- Provide a detailed description of your changes -->
5
+
6
+ ## Type of Change
7
+ <!-- Mark the relevant option with an "x" -->
8
+
9
+ - [ ] Bug fix (non-breaking change which fixes an issue)
10
+ - [ ] New feature (non-breaking change which adds functionality)
11
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
12
+ - [ ] Documentation update
13
+ - [ ] Code refactoring
14
+ - [ ] Performance improvement
15
+
16
+ ## Testing
17
+ <!-- Describe the tests you ran to verify your changes -->
18
+
19
+ - [ ] All existing tests pass
20
+ - [ ] New tests added for new functionality
21
+ - [ ] Manual testing completed
22
+
23
+ ## Checklist
24
+ <!-- Mark completed items with an "x" -->
25
+
26
+ - [ ] My code follows the style guidelines of this project (RuboCop passes)
27
+ - [ ] I have performed a self-review of my own code
28
+ - [ ] I have commented my code, particularly in hard-to-understand areas
29
+ - [ ] I have made corresponding changes to the documentation
30
+ - [ ] My changes generate no new warnings
31
+ - [ ] I have added tests that prove my fix is effective or that my feature works
32
+ - [ ] New and existing unit tests pass locally with my changes
33
+ - [ ] Any dependent changes have been merged and published
34
+
35
+ ## Related Issues
36
+ <!-- Link any related issues here using #issue-number -->
37
+
38
+ Fixes #
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main, develop ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test on Ruby ${{ matrix.ruby-version }}
12
+ runs-on: ${{ matrix.os }}
13
+
14
+ strategy:
15
+ matrix:
16
+ ruby-version: ['3.0', '3.1', '3.2', '3.3']
17
+ os: [ubuntu-latest, macos-latest, windows-latest]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Set up Ruby
23
+ uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby-version }}
26
+ bundler-cache: true
27
+
28
+ - name: Install dependencies
29
+ run: bundle install
30
+
31
+ - name: Run RuboCop
32
+ run: bundle exec rubocop
33
+
34
+ - name: Run tests
35
+ run: bundle exec rake spec
36
+
37
+ - name: Generate coverage
38
+ run: bundle exec rake coverage
39
+
40
+ - name: Build gem
41
+ run: gem build agentbill.gemspec
42
+
43
+ - name: Upload build artifacts
44
+ uses: actions/upload-artifact@v3
45
+ with:
46
+ name: gem-${{ matrix.ruby-version }}-${{ matrix.os }}
47
+ path: '*.gem'
data/.gitignore ADDED
@@ -0,0 +1,14 @@
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
+ .bundle/
13
+ vendor/bundle
14
+ .env
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
4
+ --order random
data/.rubocop.yml ADDED
@@ -0,0 +1,58 @@
1
+ # RuboCop configuration for AgentBill Ruby SDK
2
+
3
+ require:
4
+ - rubocop-performance
5
+ - rubocop-rspec
6
+
7
+ AllCops:
8
+ TargetRubyVersion: 2.6
9
+ NewCops: enable
10
+ Exclude:
11
+ - 'vendor/**/*'
12
+ - 'spec/fixtures/**/*'
13
+ - 'tmp/**/*'
14
+
15
+ # Layout
16
+ Layout/LineLength:
17
+ Max: 120
18
+ AllowedPatterns: ['\A#']
19
+
20
+ Layout/MultilineMethodCallIndentation:
21
+ EnforcedStyle: indented
22
+
23
+ # Style
24
+ Style/Documentation:
25
+ Enabled: false
26
+
27
+ Style/StringLiterals:
28
+ EnforcedStyle: single_quotes
29
+
30
+ Style/FrozenStringLiteralComment:
31
+ Enabled: true
32
+ EnforcedStyle: always
33
+
34
+ # Metrics
35
+ Metrics/MethodLength:
36
+ Max: 30
37
+ Exclude:
38
+ - 'spec/**/*'
39
+
40
+ Metrics/BlockLength:
41
+ Max: 30
42
+ Exclude:
43
+ - 'spec/**/*'
44
+ - '*.gemspec'
45
+
46
+ Metrics/ClassLength:
47
+ Max: 150
48
+
49
+ Metrics/ModuleLength:
50
+ Max: 150
51
+
52
+ # Naming
53
+ Naming/FileName:
54
+ Enabled: true
55
+
56
+ # Performance
57
+ Performance/StringReplacement:
58
+ Enabled: true
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-10-21
9
+
10
+ ### Added
11
+ - Initial release of AgentBill Ruby SDK
12
+ - OpenAI client wrapping with automatic usage tracking
13
+ - Anthropic client wrapping with automatic usage tracking
14
+ - OpenTelemetry-based tracing infrastructure
15
+ - Custom signal tracking support
16
+ - Comprehensive test suite with RSpec
17
+ - GitHub Actions CI/CD workflows
18
+ - RuboCop code quality enforcement
19
+ - Professional documentation and examples
20
+ - MIT License
21
+
22
+ ### Features
23
+ - Zero-config instrumentation for AI providers
24
+ - Automatic token and cost tracking
25
+ - Rich metadata capture
26
+ - Latency measurement
27
+ - Error tracking and reporting
28
+ - Customer-specific tracking support
29
+ - Debug logging capabilities
30
+
31
+ ### Supported Providers
32
+ - OpenAI (GPT-4, GPT-3.5, etc.)
33
+ - Anthropic (Claude 3.5 Sonnet, etc.)
34
+
35
+ ### Documentation
36
+ - Complete README with usage examples
37
+ - API documentation
38
+ - Contributing guidelines
39
+ - Security policy
40
+ - Code of conduct
41
+
42
+ [1.0.0]: https://github.com/Agent-Bill/Ruby/releases/tag/v1.0.0
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,135 @@
1
+ # Contributing to AgentBill Ruby SDK
2
+
3
+ Thank you for your interest in contributing! This document provides guidelines for contributing to the AgentBill Ruby SDK.
4
+
5
+ ## Development Setup
6
+
7
+ 1. **Fork and clone the repository**
8
+ ```bash
9
+ git clone https://github.com/YOUR_USERNAME/agentbill-ruby.git
10
+ cd agentbill-ruby
11
+ ```
12
+
13
+ 2. **Install dependencies**
14
+ ```bash
15
+ bundle install
16
+ ```
17
+
18
+ 3. **Run tests**
19
+ ```bash
20
+ bundle exec rake spec
21
+ ```
22
+
23
+ 4. **Run code quality checks**
24
+ ```bash
25
+ bundle exec rubocop
26
+ ```
27
+
28
+ ## Development Workflow
29
+
30
+ 1. **Create a feature branch**
31
+ ```bash
32
+ git checkout -b feature/your-feature-name
33
+ ```
34
+
35
+ 2. **Make your changes**
36
+ - Write clean, readable code
37
+ - Follow Ruby style guidelines (RuboCop will check this)
38
+ - Add tests for new functionality
39
+ - Update documentation as needed
40
+
41
+ 3. **Run quality checks**
42
+ ```bash
43
+ bundle exec rake ci # Runs RuboCop + tests
44
+ ```
45
+
46
+ 4. **Commit your changes**
47
+ ```bash
48
+ git add .
49
+ git commit -m "feat: Add your feature description"
50
+ ```
51
+
52
+ 5. **Push and create pull request**
53
+ ```bash
54
+ git push origin feature/your-feature-name
55
+ ```
56
+
57
+ ## Code Standards
58
+
59
+ ### Style Guide
60
+ - Follow the [Ruby Style Guide](https://rubystyle.guide/)
61
+ - Use RuboCop to check code style: `bundle exec rubocop`
62
+ - Fix auto-fixable issues: `bundle exec rubocop -a`
63
+
64
+ ### Testing
65
+ - Write RSpec tests for all new features
66
+ - Maintain minimum 90% code coverage
67
+ - Run tests: `bundle exec rake spec`
68
+ - Run with coverage: `bundle exec rake coverage`
69
+
70
+ ### Documentation
71
+ - Add YARD documentation for public methods
72
+ - Update README.md for user-facing changes
73
+ - Add examples for new features
74
+
75
+ ## Pull Request Process
76
+
77
+ 1. **Ensure all checks pass**
78
+ - All tests pass
79
+ - RuboCop has no violations
80
+ - Code coverage is maintained
81
+
82
+ 2. **Update documentation**
83
+ - Update README.md if needed
84
+ - Add CHANGELOG.md entry
85
+ - Add YARD documentation
86
+
87
+ 3. **Fill out PR template**
88
+ - Describe your changes
89
+ - Link related issues
90
+ - Check all boxes in the template
91
+
92
+ 4. **Wait for review**
93
+ - Address reviewer feedback
94
+ - Make requested changes
95
+ - Re-request review when ready
96
+
97
+ ## Adding New AI Provider Support
98
+
99
+ To add support for a new AI provider:
100
+
101
+ 1. **Add wrapper method in `lib/agentbill.rb`**
102
+ ```ruby
103
+ def wrap_provider_name(client)
104
+ # Implementation
105
+ end
106
+ ```
107
+
108
+ 2. **Add tests in `spec/agentbill_spec.rb`**
109
+ ```ruby
110
+ describe '#wrap_provider_name' do
111
+ # Tests
112
+ end
113
+ ```
114
+
115
+ 3. **Add example in `examples/`**
116
+ ```ruby
117
+ # examples/provider_name_basic.rb
118
+ ```
119
+
120
+ 4. **Update README.md** with usage example
121
+
122
+ ## Community Guidelines
123
+
124
+ - Be respectful and inclusive
125
+ - Help others learn and grow
126
+ - Provide constructive feedback
127
+ - Follow the [Code of Conduct](CODE_OF_CONDUCT.md)
128
+
129
+ ## Getting Help
130
+
131
+ - Open an issue for bugs or feature requests
132
+ - Join discussions in pull requests
133
+ - Check existing issues and PRs first
134
+
135
+ Thank you for contributing! 🎉
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in agentbill.gemspec
6
+ gemspec
7
+
8
+ group :development, :test do
9
+ gem 'rake', '~> 13.0'
10
+ gem 'rspec', '~> 3.9'
11
+ gem 'rubocop', '~> 1.21'
12
+ gem 'rubocop-performance', '~> 1.11'
13
+ gem 'rubocop-rspec', '~> 2.0'
14
+ gem 'simplecov', '~> 0.21'
15
+ gem 'webmock', '~> 3.14'
16
+ gem 'pry', '~> 0.14'
17
+ gem 'yard', '~> 0.9'
18
+ gem 'redcarpet', '~> 3.5'
19
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AgentBill
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # AgentBill Ruby SDK
2
+
3
+ OpenTelemetry-based SDK for automatically tracking and billing AI agent usage.
4
+
5
+ ## Installation
6
+
7
+ ### From GitHub (Recommended)
8
+ ```ruby
9
+ # In your Gemfile
10
+ gem 'agentbill', git: 'https://github.com/Agent-Bill/Ruby.git'
11
+ ```
12
+
13
+ ### From RubyGems
14
+ ```ruby
15
+ # In your Gemfile
16
+ gem 'agentbill'
17
+ ```
18
+
19
+ Then execute:
20
+ ```bash
21
+ bundle install
22
+ ```
23
+
24
+ ### From Source
25
+ ```bash
26
+ git clone https://github.com/Agent-Bill/Ruby.git
27
+ cd agentbill-ruby
28
+ gem build agentbill.gemspec
29
+ gem install agentbill-1.0.0.gem
30
+ ```
31
+
32
+ ## File Structure
33
+
34
+ ```
35
+ agentbill-ruby/
36
+ ├── lib/
37
+ │ ├── agentbill.rb
38
+ │ └── agentbill/
39
+ │ ├── tracer.rb
40
+ │ └── version.rb
41
+ ├── examples/
42
+ │ ├── openai_basic.rb
43
+ │ └── anthropic_basic.rb
44
+ ├── spec/
45
+ ├── README.md
46
+ ├── agentbill.gemspec
47
+ ├── Gemfile
48
+ ├── Rakefile
49
+ └── LICENSE
50
+ ```
51
+
52
+ ## Quick Start
53
+
54
+ ### OpenAI
55
+
56
+ ```ruby
57
+ require 'agentbill'
58
+ require 'openai'
59
+
60
+ # Initialize AgentBill
61
+ agentbill = AgentBill::Client.init({
62
+ api_key: 'your-api-key',
63
+ customer_id: 'customer-123',
64
+ debug: true
65
+ })
66
+
67
+ # Wrap your OpenAI client
68
+ client = agentbill.wrap_openai(OpenAI::Client.new(
69
+ access_token: 'sk-...'
70
+ ))
71
+
72
+ # Use normally - all calls are automatically tracked!
73
+ response = client.chat({
74
+ model: 'gpt-4',
75
+ messages: [{ role: 'user', content: 'Hello!' }]
76
+ })
77
+ ```
78
+
79
+ ### Anthropic
80
+
81
+ ```ruby
82
+ require 'agentbill'
83
+ require 'anthropic'
84
+
85
+ # Initialize AgentBill
86
+ agentbill = AgentBill::Client.init({
87
+ api_key: 'your-api-key',
88
+ customer_id: 'customer-123',
89
+ debug: true
90
+ })
91
+
92
+ # Wrap your Anthropic client
93
+ client = agentbill.wrap_anthropic(Anthropic::Client.new(
94
+ access_token: ENV['ANTHROPIC_API_KEY']
95
+ ))
96
+
97
+ # Use normally - all calls are automatically tracked!
98
+ response = client.messages({
99
+ model: 'claude-3-5-sonnet-20241022',
100
+ max_tokens: 1024,
101
+ messages: [{ role: 'user', content: 'Hello!' }]
102
+ })
103
+ ```
104
+
105
+ ## Features
106
+
107
+ - ✅ Zero-config instrumentation
108
+ - ✅ Accurate token & cost tracking
109
+ - ✅ Multi-provider support (OpenAI, Anthropic)
110
+ - ✅ Rich metadata capture
111
+ - ✅ OpenTelemetry-based
112
+
113
+ ## Configuration
114
+
115
+ ```ruby
116
+ config = {
117
+ api_key: 'your-api-key', # Required
118
+ base_url: 'https://...', # Optional
119
+ customer_id: 'customer-123', # Optional
120
+ debug: true # Optional
121
+ }
122
+
123
+ agentbill = AgentBill::Client.init(config)
124
+ ```
125
+
126
+ ## Publishing to RubyGems
127
+
128
+ ### Prerequisites
129
+ 1. Create a RubyGems account at https://rubygems.org/sign_up
130
+ 2. Get your API key: `gem signin`
131
+
132
+ ### Publishing Steps
133
+ ```bash
134
+ # Build the gem
135
+ gem build agentbill.gemspec
136
+
137
+ # Push to RubyGems
138
+ gem push agentbill-1.0.0.gem
139
+ ```
140
+
141
+ ## GitHub Repository Setup
142
+
143
+ 1. Create repository: `agentbill-ruby`
144
+ 2. Push all files from `lib/` directory
145
+ 3. Tag releases: `git tag v1.0.0 && git push origin v1.0.0`
146
+
147
+ ## License
148
+
149
+ MIT
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ desc 'Run all quality checks (RuboCop + tests)'
11
+ task ci: [:rubocop, :spec]
12
+
13
+ desc 'Generate code coverage report'
14
+ task :coverage do
15
+ ENV['COVERAGE'] = 'true'
16
+ Rake::Task['spec'].execute
17
+ end
18
+
19
+ desc 'Open development console'
20
+ task :console do
21
+ require 'irb'
22
+ require 'agentbill'
23
+ ARGV.clear
24
+ IRB.start
25
+ end
26
+
27
+ desc 'Generate YARD documentation'
28
+ task :doc do
29
+ system('yard doc')
30
+ end
31
+
32
+ task default: :ci
data/SECURITY.md ADDED
@@ -0,0 +1,73 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ We release security updates for the following versions:
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 1.x.x | :white_check_mark: |
10
+
11
+ ## Reporting a Vulnerability
12
+
13
+ We take security vulnerabilities seriously. If you discover a security issue, please follow responsible disclosure practices:
14
+
15
+ ### How to Report
16
+
17
+ **DO NOT** create a public GitHub issue for security vulnerabilities.
18
+
19
+ Instead, please email: security@agentbill.com
20
+
21
+ Include:
22
+ - Description of the vulnerability
23
+ - Steps to reproduce
24
+ - Potential impact
25
+ - Suggested fix (if any)
26
+
27
+ ### What to Expect
28
+
29
+ 1. **Acknowledgment**: We'll acknowledge your report within 48 hours
30
+ 2. **Investigation**: We'll investigate and keep you updated on progress
31
+ 3. **Fix**: We'll develop and test a fix
32
+ 4. **Release**: We'll release a security patch
33
+ 5. **Credit**: We'll credit you in the security advisory (unless you prefer to remain anonymous)
34
+
35
+ ### Security Best Practices
36
+
37
+ When using the AgentBill Ruby SDK:
38
+
39
+ 1. **API Keys**
40
+ - Never commit API keys to version control
41
+ - Use environment variables: `ENV['AGENTBILL_API_KEY']`
42
+ - Rotate keys regularly
43
+ - Use different keys for development/production
44
+
45
+ 2. **Dependencies**
46
+ - Keep the gem updated to the latest version
47
+ - Run `bundle update agentbill` regularly
48
+ - Monitor security advisories
49
+
50
+ 3. **Data Privacy**
51
+ - Review what data is being tracked
52
+ - Implement proper data retention policies
53
+ - Follow GDPR/CCPA guidelines if applicable
54
+
55
+ 4. **Network Security**
56
+ - Use HTTPS endpoints only
57
+ - Verify SSL certificates
58
+ - Use secure base URLs
59
+
60
+ ## Security Features
61
+
62
+ The AgentBill SDK includes:
63
+
64
+ - ✅ HTTPS-only communication
65
+ - ✅ API key authentication
66
+ - ✅ No sensitive data logged by default
67
+ - ✅ Configurable debug mode for development
68
+
69
+ ## Questions?
70
+
71
+ For general security questions, email: security@agentbill.com
72
+
73
+ Thank you for helping keep AgentBill secure! 🔒
data/agentbill.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ require_relative 'lib/agentbill/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "agentbill-sdk"
5
+ spec.version = AgentBill::VERSION
6
+ spec.authors = ["AgentBill"]
7
+ spec.email = ["support@agentbill.com"]
8
+
9
+ spec.summary = "OpenTelemetry-based SDK for tracking AI agent usage and billing"
10
+ spec.description = "Automatically track and bill AI agent usage with zero-config instrumentation for OpenAI, Anthropic, and more"
11
+ spec.homepage = "https://github.com/Agent-Bill/Ruby"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = ">= 2.7.0"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/Agent-Bill/Ruby"
17
+
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
20
+ end
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 2.0"
24
+ spec.add_development_dependency "rake", "~> 13.0"
25
+ end
@@ -0,0 +1,28 @@
1
+ require 'agentbill'
2
+ require 'anthropic'
3
+
4
+ # Initialize AgentBill with your API key
5
+ agentbill = AgentBill::Client.init({
6
+ api_key: ENV['AGENTBILL_API_KEY'] || 'your-api-key',
7
+ base_url: ENV['AGENTBILL_BASE_URL'],
8
+ customer_id: 'customer-123',
9
+ debug: true
10
+ })
11
+
12
+ # Wrap your Anthropic client
13
+ client = agentbill.wrap_anthropic(Anthropic::Client.new(
14
+ access_token: ENV['ANTHROPIC_API_KEY']
15
+ ))
16
+
17
+ # Use Anthropic normally - tracking is automatic!
18
+ response = client.messages({
19
+ model: 'claude-3-5-sonnet-20241022',
20
+ max_tokens: 1024,
21
+ messages: [
22
+ { role: 'user', content: 'What is the capital of France?' }
23
+ ]
24
+ })
25
+
26
+ puts response.dig('content', 0, 'text')
27
+
28
+ # All usage (tokens, cost, latency) is automatically tracked to your AgentBill dashboard
@@ -0,0 +1,28 @@
1
+ require 'agentbill'
2
+ require 'openai'
3
+
4
+ # Initialize AgentBill with your API key
5
+ agentbill = AgentBill::Client.init({
6
+ api_key: ENV['AGENTBILL_API_KEY'] || 'your-api-key',
7
+ base_url: ENV['AGENTBILL_BASE_URL'],
8
+ customer_id: 'customer-123',
9
+ debug: true
10
+ })
11
+
12
+ # Wrap your OpenAI client
13
+ client = agentbill.wrap_openai(OpenAI::Client.new(
14
+ access_token: ENV['OPENAI_API_KEY']
15
+ ))
16
+
17
+ # Use OpenAI normally - tracking is automatic!
18
+ response = client.chat({
19
+ model: 'gpt-4o-mini',
20
+ messages: [
21
+ { role: 'system', content: 'You are a helpful assistant.' },
22
+ { role: 'user', content: 'What is the capital of France?' }
23
+ ]
24
+ })
25
+
26
+ puts response['choices'][0]['message']['content']
27
+
28
+ # All usage (tokens, cost, latency) is automatically tracked to your AgentBill dashboard
@@ -0,0 +1,122 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'securerandom'
4
+
5
+ module AgentBill
6
+ class Span
7
+ attr_accessor :name, :trace_id, :span_id, :attributes, :start_time, :end_time, :status
8
+
9
+ def initialize(name, trace_id, span_id, attributes)
10
+ @name = name
11
+ @trace_id = trace_id
12
+ @span_id = span_id
13
+ @attributes = attributes
14
+ @start_time = (Time.now.to_f * 1_000_000_000).to_i
15
+ @end_time = nil
16
+ @status = { code: 0 }
17
+ end
18
+
19
+ def set_attributes(attrs)
20
+ @attributes.merge!(attrs)
21
+ end
22
+
23
+ def set_status(code, message = '')
24
+ @status = { code: code, message: message }
25
+ end
26
+
27
+ def finish
28
+ @end_time = (Time.now.to_f * 1_000_000_000).to_i
29
+ end
30
+ end
31
+
32
+ class Tracer
33
+ def initialize(config)
34
+ @config = config
35
+ @base_url = config[:base_url] || 'https://uenhjwdtnxtchlmqarjo.supabase.co'
36
+ @api_key = config[:api_key]
37
+ @customer_id = config[:customer_id]
38
+ @debug = config[:debug] || false
39
+ @spans = []
40
+ end
41
+
42
+ def start_span(name, attributes)
43
+ trace_id = SecureRandom.hex(16)
44
+ span_id = SecureRandom.hex(8)
45
+
46
+ attributes['service.name'] = 'agentbill-ruby-sdk'
47
+ attributes['customer.id'] = @customer_id if @customer_id
48
+
49
+ span = Span.new(name, trace_id, span_id, attributes)
50
+ @spans << span
51
+ span
52
+ end
53
+
54
+ def flush
55
+ return if @spans.empty?
56
+
57
+ payload = build_otlp_payload
58
+ uri = URI("#{@base_url}/functions/v1/otel-collector")
59
+
60
+ http = Net::HTTP.new(uri.host, uri.port)
61
+ http.use_ssl = true
62
+
63
+ request = Net::HTTP::Post.new(uri.path)
64
+ request['Authorization'] = "Bearer #{@api_key}"
65
+ request['Content-Type'] = 'application/json'
66
+ request.body = payload.to_json
67
+
68
+ response = http.request(request)
69
+
70
+ puts "AgentBill flush: #{response.code}" if @debug
71
+
72
+ @spans.clear if response.code.to_i == 200
73
+ rescue => e
74
+ puts "AgentBill flush error: #{e.message}" if @debug
75
+ end
76
+
77
+ private
78
+
79
+ def build_otlp_payload
80
+ {
81
+ resourceSpans: [{
82
+ resource: {
83
+ attributes: [
84
+ { key: 'service.name', value: { stringValue: 'agentbill-ruby-sdk' } },
85
+ { key: 'service.version', value: { stringValue: '1.0.0' } }
86
+ ]
87
+ },
88
+ scopeSpans: [{
89
+ scope: { name: 'agentbill', version: '1.0.0' },
90
+ spans: @spans.map { |span| span_to_otlp(span) }
91
+ }]
92
+ }]
93
+ }
94
+ end
95
+
96
+ def span_to_otlp(span)
97
+ {
98
+ traceId: span.trace_id,
99
+ spanId: span.span_id,
100
+ name: span.name,
101
+ kind: 1,
102
+ startTimeUnixNano: span.start_time.to_s,
103
+ endTimeUnixNano: (span.end_time || (Time.now.to_f * 1_000_000_000).to_i).to_s,
104
+ attributes: span.attributes.map { |k, v| { key: k, value: value_to_otlp(v) } },
105
+ status: span.status
106
+ }
107
+ end
108
+
109
+ def value_to_otlp(value)
110
+ case value
111
+ when String
112
+ { stringValue: value }
113
+ when Integer, Float
114
+ { intValue: value.to_i }
115
+ when TrueClass, FalseClass
116
+ { boolValue: value }
117
+ else
118
+ { stringValue: value.to_s }
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,3 @@
1
+ module AgentBill
2
+ VERSION = "1.0.1"
3
+ end
data/lib/agentbill.rb ADDED
@@ -0,0 +1,125 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'securerandom'
4
+ require_relative 'agentbill/version'
5
+ require_relative 'agentbill/tracer'
6
+
7
+ module AgentBill
8
+ class Client
9
+ attr_reader :config, :tracer
10
+
11
+ def initialize(config)
12
+ @config = config
13
+ @tracer = Tracer.new(config)
14
+ end
15
+
16
+ def self.init(config)
17
+ new(config)
18
+ end
19
+
20
+ def wrap_openai(client)
21
+ original_method = client.method(:chat)
22
+
23
+ client.define_singleton_method(:chat) do |params|
24
+ start_time = Time.now
25
+
26
+ span = @tracer.start_span('openai.chat.completion', {
27
+ 'model' => params[:model] || 'unknown',
28
+ 'provider' => 'openai'
29
+ })
30
+
31
+ begin
32
+ response = original_method.call(params)
33
+
34
+ latency = ((Time.now - start_time) * 1000).round
35
+ span.set_attributes({
36
+ 'response.prompt_tokens' => response.dig(:usage, :prompt_tokens),
37
+ 'response.completion_tokens' => response.dig(:usage, :completion_tokens),
38
+ 'response.total_tokens' => response.dig(:usage, :total_tokens),
39
+ 'latency_ms' => latency
40
+ })
41
+ span.set_status(0)
42
+
43
+ response
44
+ rescue => e
45
+ span.set_status(1, e.message)
46
+ raise
47
+ ensure
48
+ span.finish
49
+ end
50
+ end
51
+
52
+ client
53
+ end
54
+
55
+ def wrap_anthropic(client)
56
+ original_method = client.method(:messages)
57
+
58
+ client.define_singleton_method(:messages) do |params|
59
+ start_time = Time.now
60
+
61
+ span = @tracer.start_span('anthropic.message', {
62
+ 'model' => params[:model] || 'unknown',
63
+ 'provider' => 'anthropic'
64
+ })
65
+
66
+ begin
67
+ response = original_method.call(params)
68
+
69
+ latency = ((Time.now - start_time) * 1000).round
70
+ span.set_attributes({
71
+ 'response.input_tokens' => response.dig(:usage, :input_tokens),
72
+ 'response.output_tokens' => response.dig(:usage, :output_tokens),
73
+ 'latency_ms' => latency
74
+ })
75
+ span.set_status(0)
76
+
77
+ response
78
+ rescue => e
79
+ span.set_status(1, e.message)
80
+ raise
81
+ ensure
82
+ span.finish
83
+ end
84
+ end
85
+
86
+ client
87
+ end
88
+
89
+ def track_signal(event_name:, revenue: 0, data: {})
90
+ uri = URI("#{@config[:base_url] || 'https://bgwyprqxtdreuutzpbgw.supabase.co'}/functions/v1/record-signals")
91
+
92
+ payload = {
93
+ event_name: event_name,
94
+ revenue: revenue,
95
+ customer_id: @config[:customer_id],
96
+ timestamp: Time.now.to_i,
97
+ data: data
98
+ }
99
+
100
+ begin
101
+ http = Net::HTTP.new(uri.host, uri.port)
102
+ http.use_ssl = true
103
+
104
+ request = Net::HTTP::Post.new(uri.path)
105
+ request['Authorization'] = "Bearer #{@config[:api_key]}"
106
+ request['Content-Type'] = 'application/json'
107
+ request.body = payload.to_json
108
+
109
+ response = http.request(request)
110
+
111
+ if @config[:debug]
112
+ puts "[AgentBill] Signal tracked: #{event_name}, revenue: $#{revenue}"
113
+ end
114
+ rescue => e
115
+ if @config[:debug]
116
+ puts "[AgentBill] Failed to track signal: #{e.message}"
117
+ end
118
+ end
119
+ end
120
+
121
+ def flush
122
+ @tracer.flush
123
+ end
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: agentbill-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - AgentBill
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ description: Automatically track and bill AI agent usage with zero-config instrumentation
42
+ for OpenAI, Anthropic, and more
43
+ email:
44
+ - support@agentbill.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
50
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
51
+ - ".github/pull_request_template.md"
52
+ - ".github/workflows/ci.yml"
53
+ - ".gitignore"
54
+ - ".rspec"
55
+ - ".rubocop.yml"
56
+ - ".ruby-version"
57
+ - CHANGELOG.md
58
+ - CONTRIBUTING.md
59
+ - Gemfile
60
+ - LICENSE
61
+ - README.md
62
+ - Rakefile
63
+ - SECURITY.md
64
+ - agentbill.gemspec
65
+ - examples/anthropic_basic.rb
66
+ - examples/openai_basic.rb
67
+ - lib/agentbill.rb
68
+ - lib/agentbill/tracer.rb
69
+ - lib/agentbill/version.rb
70
+ homepage: https://github.com/Agent-Bill/Ruby
71
+ licenses:
72
+ - MIT
73
+ metadata:
74
+ homepage_uri: https://github.com/Agent-Bill/Ruby
75
+ source_code_uri: https://github.com/Agent-Bill/Ruby
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.7.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.4.19
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: OpenTelemetry-based SDK for tracking AI agent usage and billing
95
+ test_files: []