open_router_enhanced 1.0.0
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 +7 -0
- data/.env.example +1 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/.rubocop_todo.yml +130 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +41 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/CONTRIBUTING.md +384 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +138 -0
- data/LICENSE.txt +21 -0
- data/MIGRATION.md +556 -0
- data/README.md +1660 -0
- data/Rakefile +334 -0
- data/SECURITY.md +150 -0
- data/VCR_CONFIGURATION.md +80 -0
- data/docs/model_selection.md +637 -0
- data/docs/observability.md +430 -0
- data/docs/prompt_templates.md +422 -0
- data/docs/streaming.md +467 -0
- data/docs/structured_outputs.md +466 -0
- data/docs/tools.md +1016 -0
- data/examples/basic_completion.rb +122 -0
- data/examples/model_selection_example.rb +141 -0
- data/examples/observability_example.rb +199 -0
- data/examples/prompt_template_example.rb +184 -0
- data/examples/smart_completion_example.rb +89 -0
- data/examples/streaming_example.rb +176 -0
- data/examples/structured_outputs_example.rb +191 -0
- data/examples/tool_calling_example.rb +149 -0
- data/lib/open_router/client.rb +552 -0
- data/lib/open_router/http.rb +118 -0
- data/lib/open_router/json_healer.rb +263 -0
- data/lib/open_router/model_registry.rb +378 -0
- data/lib/open_router/model_selector.rb +462 -0
- data/lib/open_router/prompt_template.rb +290 -0
- data/lib/open_router/response.rb +371 -0
- data/lib/open_router/schema.rb +288 -0
- data/lib/open_router/streaming_client.rb +210 -0
- data/lib/open_router/tool.rb +221 -0
- data/lib/open_router/tool_call.rb +180 -0
- data/lib/open_router/usage_tracker.rb +277 -0
- data/lib/open_router/version.rb +5 -0
- data/lib/open_router.rb +123 -0
- data/sig/open_router.rbs +20 -0
- metadata +186 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0e01a3e4ebadd327148dc9f04efacd94166195e789adb0f77d20dbc83f70b234
|
|
4
|
+
data.tar.gz: 902c36d9a9d243e63ab8065456526875d19bc268450720e1ee29ee24493e7e35
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: de0e475b38181bec11bcde85a9a571eec12306eb5a755a70fae173d4743e28ee59d232adf7d3e42efc7b2693500947678848381b36b1ae30b47bdf479e51dca0
|
|
7
|
+
data.tar.gz: f91b409a150fae9af10bedddd9d0c22b6c3683096e9125e4f1310434795b0fea537ea39c1fbdf923e523e61fdc3a5ac9d9b8727e9b78c6d676e0a07d96a5663c
|
data/.env.example
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
OPENROUTER_API_KEY=sk-or-
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
|
2
|
+
|
|
3
|
+
AllCops:
|
|
4
|
+
TargetRubyVersion: 3.3
|
|
5
|
+
SuggestExtensions: false
|
|
6
|
+
|
|
7
|
+
Style/StringLiterals:
|
|
8
|
+
Enabled: true
|
|
9
|
+
EnforcedStyle: double_quotes
|
|
10
|
+
|
|
11
|
+
Style/StringLiteralsInInterpolation:
|
|
12
|
+
Enabled: true
|
|
13
|
+
EnforcedStyle: double_quotes
|
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2025-10-07 18:18:35 UTC using RuboCop version 1.79.2.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: Severity, Include.
|
|
11
|
+
# Include: **/*.gemspec
|
|
12
|
+
Gemspec/RequiredRubyVersion:
|
|
13
|
+
Exclude:
|
|
14
|
+
- 'open_router_enhanced.gemspec'
|
|
15
|
+
|
|
16
|
+
# Offense count: 1
|
|
17
|
+
Lint/ShadowedException:
|
|
18
|
+
Exclude:
|
|
19
|
+
- 'lib/open_router/model_registry.rb'
|
|
20
|
+
|
|
21
|
+
# Offense count: 19
|
|
22
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
23
|
+
# Configuration parameters: AutoCorrect, IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
|
|
24
|
+
Lint/UnusedBlockArgument:
|
|
25
|
+
Exclude:
|
|
26
|
+
- 'spec/force_structured_output_spec.rb'
|
|
27
|
+
- 'spec/integration/structured_output_flow_spec.rb'
|
|
28
|
+
|
|
29
|
+
# Offense count: 24
|
|
30
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
|
31
|
+
Metrics/AbcSize:
|
|
32
|
+
Max: 69
|
|
33
|
+
|
|
34
|
+
# Offense count: 183
|
|
35
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
36
|
+
# AllowedMethods: refine
|
|
37
|
+
Metrics/BlockLength:
|
|
38
|
+
Max: 464
|
|
39
|
+
|
|
40
|
+
# Offense count: 7
|
|
41
|
+
# Configuration parameters: CountComments, CountAsOne.
|
|
42
|
+
Metrics/ClassLength:
|
|
43
|
+
Max: 339
|
|
44
|
+
|
|
45
|
+
# Offense count: 16
|
|
46
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
47
|
+
Metrics/CyclomaticComplexity:
|
|
48
|
+
Max: 21
|
|
49
|
+
|
|
50
|
+
# Offense count: 44
|
|
51
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
52
|
+
Metrics/MethodLength:
|
|
53
|
+
Max: 42
|
|
54
|
+
|
|
55
|
+
# Offense count: 6
|
|
56
|
+
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
57
|
+
Metrics/ParameterLists:
|
|
58
|
+
Max: 10
|
|
59
|
+
|
|
60
|
+
# Offense count: 13
|
|
61
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
62
|
+
Metrics/PerceivedComplexity:
|
|
63
|
+
Max: 22
|
|
64
|
+
|
|
65
|
+
# Offense count: 1
|
|
66
|
+
Naming/ConstantName:
|
|
67
|
+
Exclude:
|
|
68
|
+
- 'spec/response_healing_spec.rb'
|
|
69
|
+
|
|
70
|
+
# Offense count: 4
|
|
71
|
+
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
|
|
72
|
+
# NamePrefix: is_, has_, have_, does_
|
|
73
|
+
# ForbiddenPrefixes: is_, has_, have_, does_
|
|
74
|
+
# AllowedMethods: is_a?
|
|
75
|
+
# MethodDefinitionMacros: define_method, define_singleton_method
|
|
76
|
+
Naming/PredicatePrefix:
|
|
77
|
+
Exclude:
|
|
78
|
+
- 'spec/**/*'
|
|
79
|
+
- 'lib/open_router/model_registry.rb'
|
|
80
|
+
- 'lib/open_router/response.rb'
|
|
81
|
+
|
|
82
|
+
# Offense count: 6
|
|
83
|
+
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
84
|
+
# SupportedStyles: snake_case, normalcase, non_integer
|
|
85
|
+
# AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
|
86
|
+
Naming/VariableNumber:
|
|
87
|
+
Exclude:
|
|
88
|
+
- 'spec/vcr/prompt_template_spec.rb'
|
|
89
|
+
|
|
90
|
+
# Offense count: 9
|
|
91
|
+
# Configuration parameters: AllowedConstants.
|
|
92
|
+
Style/Documentation:
|
|
93
|
+
Exclude:
|
|
94
|
+
- 'spec/**/*'
|
|
95
|
+
- 'test/**/*'
|
|
96
|
+
- 'lib/open_router.rb'
|
|
97
|
+
- 'lib/open_router/client.rb'
|
|
98
|
+
- 'lib/open_router/http.rb'
|
|
99
|
+
- 'lib/open_router/model_registry.rb'
|
|
100
|
+
- 'lib/open_router/response.rb'
|
|
101
|
+
- 'lib/open_router/schema.rb'
|
|
102
|
+
- 'lib/open_router/tool.rb'
|
|
103
|
+
- 'lib/open_router/tool_call.rb'
|
|
104
|
+
|
|
105
|
+
# Offense count: 8
|
|
106
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
107
|
+
Style/IfUnlessModifier:
|
|
108
|
+
Exclude:
|
|
109
|
+
- 'lib/open_router/client.rb'
|
|
110
|
+
- 'lib/open_router/model_registry.rb'
|
|
111
|
+
|
|
112
|
+
# Offense count: 12
|
|
113
|
+
Style/MultilineBlockChain:
|
|
114
|
+
Exclude:
|
|
115
|
+
- 'spec/vcr/error_handling_spec.rb'
|
|
116
|
+
- 'spec/vcr/model_fallback_spec.rb'
|
|
117
|
+
|
|
118
|
+
# Offense count: 2
|
|
119
|
+
# Configuration parameters: AllowedMethods.
|
|
120
|
+
# AllowedMethods: respond_to_missing?
|
|
121
|
+
Style/OptionalBooleanParameter:
|
|
122
|
+
Exclude:
|
|
123
|
+
- 'lib/open_router/schema.rb'
|
|
124
|
+
|
|
125
|
+
# Offense count: 37
|
|
126
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
127
|
+
# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
128
|
+
# URISchemes: http, https
|
|
129
|
+
Layout/LineLength:
|
|
130
|
+
Max: 210
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.3.9
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [1.0.0] - 2025-10-07
|
|
4
|
+
|
|
5
|
+
### Major Features
|
|
6
|
+
- **Tool Calling**: Complete function calling support with DSL-based tool definitions and automatic validation
|
|
7
|
+
- **Structured Outputs**: Native and forced JSON schema support with automatic response healing
|
|
8
|
+
- **Model Selection**: Intelligent model selection with fluent DSL, capability detection, and cost optimization
|
|
9
|
+
- **Model Fallbacks**: Automatic failover routing with model arrays for reliability
|
|
10
|
+
- **Response Healing**: Self-correcting malformed JSON outputs from non-native structured output models
|
|
11
|
+
- **Streaming Client**: Real-time streaming with comprehensive callback system
|
|
12
|
+
- **Usage Tracking**: Token usage and cost analytics with detailed metrics
|
|
13
|
+
- **Prompt Templates**: Reusable templates with variable interpolation
|
|
14
|
+
|
|
15
|
+
### Enhanced
|
|
16
|
+
- **Model Registry**: Local caching with automatic capability detection and cost calculation
|
|
17
|
+
- **Response Object**: Rich metadata including tokens, costs, cache hits, and performance analytics
|
|
18
|
+
- **Error Handling**: Comprehensive error hierarchy with specific error types for better debugging
|
|
19
|
+
- **VCR Testing**: Complete real API integration testing coverage
|
|
20
|
+
- **Documentation**: Extensive guides, examples, and API reference
|
|
21
|
+
|
|
22
|
+
### Compatibility
|
|
23
|
+
- Full backward compatibility with original OpenRouter gem
|
|
24
|
+
- Ruby 3.0+ support
|
|
25
|
+
- Optional dependencies for enhanced features (json-schema for validation)
|
|
26
|
+
|
|
27
|
+
## [0.3.0] - 2024-05-03
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- Uses Faraday's built-in JSON mode
|
|
31
|
+
- Added support for configuring Faraday and its middleware
|
|
32
|
+
- Spec creates a STDOUT logger by default (headers, bodies, errors)
|
|
33
|
+
- Spec filters Bearer token from logs by default
|
|
34
|
+
|
|
35
|
+
## [0.1.0] - 2024-03-19
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
- Initial release of OpenRouter Ruby gem
|
|
39
|
+
- Basic chat completion support
|
|
40
|
+
- Model selection and routing
|
|
41
|
+
- OpenRouter API integration
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive environment for our community include:
|
|
12
|
+
|
|
13
|
+
* Demonstrating empathy and kindness toward other people
|
|
14
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
* Giving and gracefully accepting constructive feedback
|
|
16
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
|
17
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior include:
|
|
20
|
+
|
|
21
|
+
* The use of sexualized language or imagery, and sexual attention or
|
|
22
|
+
advances of any kind
|
|
23
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
24
|
+
* Public or private harassment
|
|
25
|
+
* Publishing others' private information, such as a physical or email
|
|
26
|
+
address, without their explicit permission
|
|
27
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
28
|
+
professional setting
|
|
29
|
+
|
|
30
|
+
## Enforcement Responsibilities
|
|
31
|
+
|
|
32
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
33
|
+
|
|
34
|
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
|
35
|
+
|
|
36
|
+
## Scope
|
|
37
|
+
|
|
38
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
|
39
|
+
|
|
40
|
+
## Enforcement
|
|
41
|
+
|
|
42
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at opensource@ericstiens.dev. All complaints will be reviewed and investigated promptly and fairly.
|
|
43
|
+
|
|
44
|
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
|
45
|
+
|
|
46
|
+
## Enforcement Guidelines
|
|
47
|
+
|
|
48
|
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
|
49
|
+
|
|
50
|
+
### 1. Correction
|
|
51
|
+
|
|
52
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
|
53
|
+
|
|
54
|
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
|
55
|
+
|
|
56
|
+
### 2. Warning
|
|
57
|
+
|
|
58
|
+
**Community Impact**: A violation through a single incident or series of actions.
|
|
59
|
+
|
|
60
|
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
|
61
|
+
|
|
62
|
+
### 3. Temporary Ban
|
|
63
|
+
|
|
64
|
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
|
65
|
+
|
|
66
|
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
|
67
|
+
|
|
68
|
+
### 4. Permanent Ban
|
|
69
|
+
|
|
70
|
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
|
71
|
+
|
|
72
|
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
|
73
|
+
|
|
74
|
+
## Attribution
|
|
75
|
+
|
|
76
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
|
|
77
|
+
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
78
|
+
|
|
79
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
|
80
|
+
|
|
81
|
+
[homepage]: https://www.contributor-covenant.org
|
|
82
|
+
|
|
83
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
84
|
+
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Contributing to OpenRouter Ruby Gem
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to the OpenRouter Ruby gem! This document provides guidelines for contributing to the project.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Getting Started](#getting-started)
|
|
8
|
+
- [Development Setup](#development-setup)
|
|
9
|
+
- [Contributing Process](#contributing-process)
|
|
10
|
+
- [Code Standards](#code-standards)
|
|
11
|
+
- [Testing Guidelines](#testing-guidelines)
|
|
12
|
+
- [Documentation](#documentation)
|
|
13
|
+
- [Submitting Changes](#submitting-changes)
|
|
14
|
+
- [Release Process](#release-process)
|
|
15
|
+
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
### Prerequisites
|
|
19
|
+
|
|
20
|
+
- Ruby 3.2.2 or higher
|
|
21
|
+
- Bundler
|
|
22
|
+
- Git
|
|
23
|
+
- OpenRouter API key (for VCR tests)
|
|
24
|
+
|
|
25
|
+
### Development Setup
|
|
26
|
+
|
|
27
|
+
1. **Fork and Clone**
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/YOUR_USERNAME/open_router.git
|
|
30
|
+
cd open_router
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. **Install Dependencies**
|
|
34
|
+
```bash
|
|
35
|
+
bundle install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
3. **Set Environment Variables**
|
|
39
|
+
```bash
|
|
40
|
+
export OPENROUTER_API_KEY="your_api_key_here"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
4. **Run Tests**
|
|
44
|
+
```bash
|
|
45
|
+
bundle exec rspec
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
5. **Interactive Console**
|
|
49
|
+
```bash
|
|
50
|
+
bundle exec pry -I lib -r open_router
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Contributing Process
|
|
54
|
+
|
|
55
|
+
### 1. Choose an Issue
|
|
56
|
+
|
|
57
|
+
- Look for issues labeled `good first issue` for newcomers
|
|
58
|
+
- Check existing issues or create a new one for discussion
|
|
59
|
+
- Comment on the issue to indicate you're working on it
|
|
60
|
+
|
|
61
|
+
### 2. Create a Feature Branch
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
git checkout -b feature/your-feature-name
|
|
65
|
+
# or
|
|
66
|
+
git checkout -b fix/your-bug-fix
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3. Follow Development Workflow
|
|
70
|
+
|
|
71
|
+
1. **Write Tests First** (TDD approach)
|
|
72
|
+
- Unit tests for new functionality
|
|
73
|
+
- VCR integration tests for API interactions
|
|
74
|
+
- Edge case and error handling tests
|
|
75
|
+
|
|
76
|
+
2. **Implement Feature**
|
|
77
|
+
- Follow existing code patterns
|
|
78
|
+
- Add comprehensive error handling
|
|
79
|
+
- Include documentation comments
|
|
80
|
+
|
|
81
|
+
3. **Update Documentation**
|
|
82
|
+
- Update relevant docs/ files
|
|
83
|
+
- Add examples to README if needed
|
|
84
|
+
- Update CHANGELOG.md
|
|
85
|
+
|
|
86
|
+
4. **Test Thoroughly**
|
|
87
|
+
```bash
|
|
88
|
+
bundle exec rspec
|
|
89
|
+
bundle exec rubocop
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Code Standards
|
|
93
|
+
|
|
94
|
+
### Ruby Style
|
|
95
|
+
|
|
96
|
+
Follow the existing codebase patterns and RuboCop configuration:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Check style
|
|
100
|
+
bundle exec rubocop
|
|
101
|
+
|
|
102
|
+
# Auto-fix issues
|
|
103
|
+
bundle exec rubocop -a
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Design Patterns
|
|
107
|
+
|
|
108
|
+
#### DSL Design
|
|
109
|
+
- Use descriptive method names
|
|
110
|
+
- Chain methods fluently
|
|
111
|
+
- Provide sensible defaults
|
|
112
|
+
- Include parameter validation
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# Good
|
|
116
|
+
tool = OpenRouter::Tool.define do
|
|
117
|
+
name "search_api"
|
|
118
|
+
description "Search external API for information"
|
|
119
|
+
|
|
120
|
+
parameters do
|
|
121
|
+
string :query, required: true, description: "Search query"
|
|
122
|
+
integer :limit, minimum: 1, maximum: 100, default: 10
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Bad
|
|
127
|
+
tool = OpenRouter::Tool.new(name: "search", params: { q: { type: "string" } })
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### Error Handling
|
|
131
|
+
- Use specific error classes
|
|
132
|
+
- Provide helpful error messages
|
|
133
|
+
- Include context in errors
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
# Good
|
|
137
|
+
raise OpenRouter::ToolCallError,
|
|
138
|
+
"Tool '#{tool_name}' validation failed: #{validation_errors.join(', ')}"
|
|
139
|
+
|
|
140
|
+
# Bad
|
|
141
|
+
raise StandardError, "Invalid tool"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Backward Compatibility
|
|
145
|
+
- Ensure all changes are backward compatible
|
|
146
|
+
- Use feature flags for experimental features
|
|
147
|
+
- Deprecate features gradually with warnings
|
|
148
|
+
|
|
149
|
+
### Documentation
|
|
150
|
+
|
|
151
|
+
#### Code Comments
|
|
152
|
+
- Document complex algorithms
|
|
153
|
+
- Explain non-obvious business logic
|
|
154
|
+
- Include examples for public methods
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
# Calculates the estimated cost for a completion request.
|
|
158
|
+
# Takes into account both input and output token costs.
|
|
159
|
+
#
|
|
160
|
+
# @param model [String] The model identifier
|
|
161
|
+
# @param input_tokens [Integer] Number of input tokens
|
|
162
|
+
# @param output_tokens [Integer] Number of output tokens
|
|
163
|
+
# @return [Float] Estimated cost in USD
|
|
164
|
+
def calculate_estimated_cost(model, input_tokens:, output_tokens:)
|
|
165
|
+
# Implementation...
|
|
166
|
+
end
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### Markdown Documentation
|
|
170
|
+
- Use clear headings and structure
|
|
171
|
+
- Include practical examples
|
|
172
|
+
- Provide troubleshooting sections
|
|
173
|
+
- Link between related documentation
|
|
174
|
+
|
|
175
|
+
## Testing Guidelines
|
|
176
|
+
|
|
177
|
+
### Test Organization
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
spec/
|
|
181
|
+
├── unit/ # Fast unit tests
|
|
182
|
+
│ ├── tool_spec.rb
|
|
183
|
+
│ ├── schema_spec.rb
|
|
184
|
+
│ └── model_selector_spec.rb
|
|
185
|
+
├── integration/ # Cross-module integration tests
|
|
186
|
+
│ └── client_integration_spec.rb
|
|
187
|
+
├── vcr/ # Real API interaction tests
|
|
188
|
+
│ ├── tool_calling_spec.rb
|
|
189
|
+
│ ├── structured_outputs_spec.rb
|
|
190
|
+
│ └── model_registry_spec.rb
|
|
191
|
+
└── support/
|
|
192
|
+
└── vcr.rb # VCR configuration
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Test Writing Guidelines
|
|
196
|
+
|
|
197
|
+
#### Unit Tests
|
|
198
|
+
```ruby
|
|
199
|
+
# Good: Clear, focused test
|
|
200
|
+
RSpec.describe OpenRouter::Tool do
|
|
201
|
+
describe "#to_json_schema" do
|
|
202
|
+
it "generates valid JSON schema for simple parameters" do
|
|
203
|
+
tool = described_class.define do
|
|
204
|
+
name "test_tool"
|
|
205
|
+
parameters do
|
|
206
|
+
string :query, required: true
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
schema = tool.to_json_schema
|
|
211
|
+
expect(schema[:parameters][:required]).to include("query")
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### VCR Tests
|
|
218
|
+
```ruby
|
|
219
|
+
# Good: Real API interaction test
|
|
220
|
+
RSpec.describe "Tool Calling", :vcr do
|
|
221
|
+
it "handles real tool calling workflow" do
|
|
222
|
+
response = client.complete(
|
|
223
|
+
messages,
|
|
224
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
225
|
+
tools: [tool],
|
|
226
|
+
tool_choice: "auto"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
expect(response.has_tool_calls?).to be true
|
|
230
|
+
expect(response.tool_calls.first.name).to eq("test_tool")
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### VCR Best Practices
|
|
236
|
+
|
|
237
|
+
1. **Use Descriptive Cassette Names**
|
|
238
|
+
```ruby
|
|
239
|
+
it "handles complex tool parameters", vcr: { cassette_name: "tool_complex_parameters" } do
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
2. **Filter Sensitive Data**
|
|
243
|
+
- API keys are automatically filtered
|
|
244
|
+
- Add custom filters for other sensitive data
|
|
245
|
+
|
|
246
|
+
3. **Keep Cassettes Fresh**
|
|
247
|
+
```bash
|
|
248
|
+
# Re-record all cassettes
|
|
249
|
+
rm -rf spec/fixtures/vcr_cassettes/
|
|
250
|
+
bundle exec rspec spec/vcr/
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Documentation
|
|
254
|
+
|
|
255
|
+
### Types of Documentation
|
|
256
|
+
|
|
257
|
+
1. **API Documentation** - In-code documentation for public methods
|
|
258
|
+
2. **User Guides** - Step-by-step tutorials in docs/
|
|
259
|
+
3. **Examples** - Working examples in examples/
|
|
260
|
+
4. **README** - Overview and quick start guide
|
|
261
|
+
5. **CHANGELOG** - Version history and breaking changes
|
|
262
|
+
|
|
263
|
+
### Documentation Standards
|
|
264
|
+
|
|
265
|
+
- **Clear Examples**: Always include working code examples
|
|
266
|
+
- **Complete Coverage**: Document all public APIs
|
|
267
|
+
- **Troubleshooting**: Include common issues and solutions
|
|
268
|
+
- **Links**: Cross-reference related documentation
|
|
269
|
+
|
|
270
|
+
## Submitting Changes
|
|
271
|
+
|
|
272
|
+
### Pull Request Process
|
|
273
|
+
|
|
274
|
+
1. **Ensure Quality**
|
|
275
|
+
```bash
|
|
276
|
+
bundle exec rspec # All tests pass
|
|
277
|
+
bundle exec rubocop # Style checks pass
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
2. **Update Documentation**
|
|
281
|
+
- Add examples for new features
|
|
282
|
+
- Update relevant docs/ files
|
|
283
|
+
- Update CHANGELOG.md
|
|
284
|
+
|
|
285
|
+
3. **Create Pull Request**
|
|
286
|
+
- Use descriptive title and description
|
|
287
|
+
- Reference related issues
|
|
288
|
+
- Include testing notes
|
|
289
|
+
|
|
290
|
+
4. **Pull Request Template**
|
|
291
|
+
```markdown
|
|
292
|
+
## Description
|
|
293
|
+
Brief description of changes
|
|
294
|
+
|
|
295
|
+
## Type of Change
|
|
296
|
+
- [ ] Bug fix
|
|
297
|
+
- [ ] New feature
|
|
298
|
+
- [ ] Breaking change
|
|
299
|
+
- [ ] Documentation update
|
|
300
|
+
|
|
301
|
+
## Testing
|
|
302
|
+
- [ ] Unit tests added/updated
|
|
303
|
+
- [ ] VCR tests added/updated
|
|
304
|
+
- [ ] Manual testing completed
|
|
305
|
+
|
|
306
|
+
## Checklist
|
|
307
|
+
- [ ] Code follows style guidelines
|
|
308
|
+
- [ ] Self-review completed
|
|
309
|
+
- [ ] Documentation updated
|
|
310
|
+
- [ ] CHANGELOG.md updated
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Code Review Guidelines
|
|
314
|
+
|
|
315
|
+
#### For Authors
|
|
316
|
+
- Respond to feedback promptly
|
|
317
|
+
- Ask questions if feedback is unclear
|
|
318
|
+
- Make requested changes or explain reasoning
|
|
319
|
+
|
|
320
|
+
#### For Reviewers
|
|
321
|
+
- Be constructive and specific
|
|
322
|
+
- Focus on code quality and maintainability
|
|
323
|
+
- Test the changes locally when possible
|
|
324
|
+
|
|
325
|
+
## Release Process
|
|
326
|
+
|
|
327
|
+
### Version Numbering
|
|
328
|
+
|
|
329
|
+
Follow [Semantic Versioning](https://semver.org/):
|
|
330
|
+
|
|
331
|
+
- **MAJOR**: Breaking changes
|
|
332
|
+
- **MINOR**: New features (backward compatible)
|
|
333
|
+
- **PATCH**: Bug fixes (backward compatible)
|
|
334
|
+
|
|
335
|
+
### Release Checklist
|
|
336
|
+
|
|
337
|
+
1. **Update Version**
|
|
338
|
+
```ruby
|
|
339
|
+
# lib/open_router/version.rb
|
|
340
|
+
VERSION = "0.4.0"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
2. **Update CHANGELOG.md**
|
|
344
|
+
- Move items from [Unreleased] to new version
|
|
345
|
+
- Add release date
|
|
346
|
+
- Create new [Unreleased] section
|
|
347
|
+
|
|
348
|
+
3. **Run Full Test Suite**
|
|
349
|
+
```bash
|
|
350
|
+
bundle exec rspec
|
|
351
|
+
bundle exec rspec spec/vcr/ # With fresh recordings
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
4. **Update Documentation**
|
|
355
|
+
- Ensure README is current
|
|
356
|
+
- Verify all examples work
|
|
357
|
+
- Check link validity
|
|
358
|
+
|
|
359
|
+
5. **Create Release**
|
|
360
|
+
```bash
|
|
361
|
+
git tag v0.4.0
|
|
362
|
+
git push origin v0.4.0
|
|
363
|
+
gem build open_router.gemspec
|
|
364
|
+
gem push open_router-0.4.0.gem
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Getting Help
|
|
368
|
+
|
|
369
|
+
- **Questions**: Open a discussion or issue
|
|
370
|
+
- **Bugs**: Create an issue with reproduction steps
|
|
371
|
+
- **Features**: Discuss in an issue before implementing
|
|
372
|
+
|
|
373
|
+
## Code of Conduct
|
|
374
|
+
|
|
375
|
+
This project follows our [Code of Conduct](CODE_OF_CONDUCT.md). Please read and follow it in all interactions.
|
|
376
|
+
|
|
377
|
+
## Recognition
|
|
378
|
+
|
|
379
|
+
Contributors are recognized in:
|
|
380
|
+
- CHANGELOG.md for significant contributions
|
|
381
|
+
- GitHub contributors page
|
|
382
|
+
- Special thanks in release notes
|
|
383
|
+
|
|
384
|
+
Thank you for contributing to OpenRouterEnhanced Ruby gem! 🚀
|
data/Gemfile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
# Specify your gem's dependencies in open_router.gemspec
|
|
6
|
+
gemspec
|
|
7
|
+
|
|
8
|
+
gem "activesupport", ">= 6.0"
|
|
9
|
+
gem "json-schema"
|
|
10
|
+
|
|
11
|
+
group :development, :test do
|
|
12
|
+
gem "dotenv", ">= 2"
|
|
13
|
+
gem "pry", ">= 0.14"
|
|
14
|
+
gem "vcr", "~> 6.2"
|
|
15
|
+
gem "webmock", "~> 3.19"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
group :development do
|
|
19
|
+
gem "rake", "~> 13.0"
|
|
20
|
+
gem "rspec", "~> 3.0"
|
|
21
|
+
gem "rubocop", require: false
|
|
22
|
+
end
|