vibe-sort 0.2.0 → 0.3.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.
@@ -6,30 +6,40 @@ The main public interface for the VibeSort gem.
6
6
 
7
7
  ### Class Methods
8
8
 
9
- #### `new(api_key:, temperature: 0.0)`
9
+ #### `new(api_key:, temperature: 0.0, provider: :openai, model: nil)`
10
10
 
11
11
  Creates a new VibeSort client instance.
12
12
 
13
13
  **Parameters:**
14
14
 
15
- - `api_key` (String, required): Your OpenAI API key
15
+ - `api_key` (String, required): API key for the selected provider
16
16
  - `temperature` (Float, optional): Model temperature setting (default: 0.0)
17
17
  - Range: 0.0 to 2.0
18
18
  - Lower values (0.0-0.3): More deterministic and consistent
19
19
  - Higher values (0.7-2.0): More random and creative
20
+ - Ignored by providers whose current models do not accept it (Anthropic)
21
+ - `provider` (Symbol or String, optional): LLM provider (default: `:openai`)
22
+ - Supported: `:openai`, `:anthropic`, `:gemini`, `:groq`, `:spacexai`
23
+ - `model` (String, optional): Model ID override (default: the provider's default model)
20
24
 
21
25
  **Returns:** `VibeSort::Client` instance
22
26
 
23
27
  **Raises:**
24
28
 
25
- - `ArgumentError`: If api_key is nil or empty
29
+ - `ArgumentError`: If api_key is nil or empty, or the provider is unknown
26
30
 
27
31
  **Example:**
28
32
 
29
33
  ```ruby
30
- # Basic initialization
34
+ # Basic initialization (OpenAI, default provider)
31
35
  client = VibeSort::Client.new(api_key: ENV['OPENAI_API_KEY'])
32
36
 
37
+ # Anthropic Claude
38
+ client = VibeSort::Client.new(provider: :anthropic, api_key: ENV['ANTHROPIC_API_KEY'])
39
+
40
+ # Google Gemini with a custom model
41
+ client = VibeSort::Client.new(provider: :gemini, api_key: ENV['GEMINI_API_KEY'], model: 'gemini-2.5-pro')
42
+
33
43
  # With custom temperature
34
44
  client = VibeSort::Client.new(
35
45
  api_key: ENV['OPENAI_API_KEY'],
@@ -41,7 +51,7 @@ client = VibeSort::Client.new(
41
51
 
42
52
  #### `sort(array)`
43
53
 
44
- Sorts an array of numbers and/or strings using OpenAI's API.
54
+ Sorts an array of numbers and/or strings using the configured provider's API.
45
55
 
46
56
  **Parameters:**
47
57
 
@@ -100,25 +110,28 @@ Configuration object for VibeSort. Usually not used directly by end users.
100
110
 
101
111
  ### Class Methods
102
112
 
103
- #### `new(api_key:, temperature: 0.0)`
113
+ #### `new(api_key:, temperature: 0.0, provider: :openai, model: nil)`
104
114
 
105
115
  Creates a new configuration object.
106
116
 
107
117
  **Parameters:**
108
118
 
109
- - `api_key` (String, required): OpenAI API key
119
+ - `api_key` (String, required): API key for the selected provider
110
120
  - `temperature` (Float, optional): Model temperature (default: 0.0)
121
+ - `provider` (Symbol or String, optional): `:openai` (default), `:anthropic`, `:gemini`, `:groq`, or `:spacexai`
122
+ - `model` (String, optional): Model ID override (nil uses the provider's default)
111
123
 
112
124
  **Raises:**
113
125
 
114
- - `ArgumentError`: If api_key is nil or empty
126
+ - `ArgumentError`: If api_key is nil or empty, or the provider is unknown
115
127
 
116
128
  **Example:**
117
129
 
118
130
  ```ruby
119
131
  config = VibeSort::Configuration.new(
120
132
  api_key: "sk-...",
121
- temperature: 0.0
133
+ provider: :anthropic,
134
+ model: "claude-haiku-4-5"
122
135
  )
123
136
  ```
124
137
 
@@ -136,11 +149,23 @@ Returns the configured temperature setting (read-only).
136
149
 
137
150
  **Returns:** Float
138
151
 
152
+ #### `provider`
153
+
154
+ Returns the configured provider (read-only).
155
+
156
+ **Returns:** Symbol
157
+
158
+ #### `model`
159
+
160
+ Returns the configured model override, or nil when using the provider default (read-only).
161
+
162
+ **Returns:** String or nil
163
+
139
164
  ---
140
165
 
141
166
  ## VibeSort::Sorter
142
167
 
143
- Internal class that handles API communication. Not intended for direct use.
168
+ Internal class that dispatches the sorting operation to the configured provider adapter. Not intended for direct use.
144
169
 
145
170
  ### Class Methods
146
171
 
@@ -156,7 +181,7 @@ Creates a new sorter instance.
156
181
 
157
182
  #### `perform(array)`
158
183
 
159
- Performs the sorting operation via OpenAI API.
184
+ Performs the sorting operation via the configured provider's API.
160
185
 
161
186
  **Parameters:**
162
187
 
@@ -170,17 +195,30 @@ Performs the sorting operation via OpenAI API.
170
195
 
171
196
  ### Constants
172
197
 
173
- #### `OPENAI_API_URL`
198
+ #### `PROVIDER_CLASSES`
199
+
200
+ Maps provider symbols to adapter classes.
201
+
202
+ **Value:** `{ openai:, anthropic:, gemini:, groq:, spacexai: }`
203
+
204
+ ---
174
205
 
175
- The OpenAI API endpoint URL.
206
+ ## VibeSort::Providers
176
207
 
177
- **Value:** `"https://api.openai.com/v1/chat/completions"`
208
+ Internal provider adapters. `Providers::Base` holds the shared prompt, Faraday HTTP plumbing, and response validation; each subclass maps one provider's request/response wire format.
178
209
 
179
- #### `DEFAULT_MODEL`
210
+ | Adapter | Endpoint | `DEFAULT_MODEL` |
211
+ |---|---|---|
212
+ | `Providers::OpenAI` | `https://api.openai.com/v1/chat/completions` | `gpt-4o-mini` |
213
+ | `Providers::Anthropic` | `https://api.anthropic.com/v1/messages` | `claude-opus-4-8` |
214
+ | `Providers::Gemini` | `https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent` | `gemini-2.5-flash` |
215
+ | `Providers::Groq` | `https://api.groq.com/openai/v1/chat/completions` | `llama-3.3-70b-versatile` |
216
+ | `Providers::SpaceXAI` | `https://api.x.ai/v1/chat/completions` | `grok-4` |
180
217
 
181
- The default GPT model used for sorting.
218
+ Notes:
182
219
 
183
- **Value:** `"gpt-3.5-turbo-1106"`
220
+ - The Anthropic adapter uses structured outputs (JSON schema) and does not send `temperature` (rejected by current Claude models)
221
+ - The Groq and SpaceXAI adapters subclass `Providers::OpenAI` (OpenAI-compatible APIs)
184
222
 
185
223
  ---
186
224
 
@@ -269,11 +307,13 @@ All sorting operations return a consistent hash structure:
269
307
 
270
308
  ### API Errors
271
309
 
310
+ The `{Provider}` prefix names the configured provider (OpenAI, Anthropic, Gemini, Groq, or SpaceXAI):
311
+
272
312
  | Error Message Pattern | Cause | Solution |
273
313
  |----------------------|-------|----------|
274
- | "OpenAI API error: Invalid API key" | Invalid or missing API key | Check API key |
275
- | "OpenAI API error: Rate limit exceeded" | Too many requests | Wait and retry |
276
- | "OpenAI API error: HTTP {status}" | HTTP error | Check API status |
314
+ | "{Provider} API error: Invalid API key" | Invalid or missing API key | Check API key |
315
+ | "{Provider} API error: Rate limit exceeded" | Too many requests | Wait and retry |
316
+ | "{Provider} API error: HTTP {status}" | HTTP error | Check API status |
277
317
 
278
318
  ### Response Parsing Errors
279
319
 
@@ -412,14 +452,14 @@ results = threads.map(&:value)
412
452
 
413
453
  ## Environment Variables
414
454
 
415
- ### OPENAI_API_KEY
416
-
417
- Your OpenAI API key. Required for all operations.
418
-
419
- **Setup:**
455
+ Set the API key for whichever provider you use:
420
456
 
421
457
  ```bash
422
- export OPENAI_API_KEY='sk-your-key-here'
458
+ export OPENAI_API_KEY='sk-your-key-here' # provider: :openai (default)
459
+ export ANTHROPIC_API_KEY='your-key-here' # provider: :anthropic
460
+ export GEMINI_API_KEY='your-key-here' # provider: :gemini
461
+ export GROQ_API_KEY='your-key-here' # provider: :groq
462
+ export XAI_API_KEY='your-key-here' # provider: :spacexai
423
463
  ```
424
464
 
425
465
  **Usage:**
@@ -432,9 +472,9 @@ client = VibeSort::Client.new(api_key: ENV['OPENAI_API_KEY'])
432
472
 
433
473
  ## Version
434
474
 
435
- Current version: `0.1.0`
475
+ Current version: `0.3.0`
436
476
 
437
477
  ```ruby
438
478
  VibeSort::VERSION
439
- # => "0.1.0"
479
+ # => "0.3.0"
440
480
  ```
data/docs/architecture.md CHANGED
@@ -20,24 +20,36 @@ VibeSort follows a layered architecture with clear separation of concerns:
20
20
 
21
21
  ┌─────────────────────────────────────────┐
22
22
  │ VibeSort::Configuration │
23
+ │ - Provider selection │
23
24
  │ - API key management │
25
+ │ - Model override │
24
26
  │ - Temperature settings │
25
27
  └─────────────────┬───────────────────────┘
26
28
 
27
29
 
28
30
  ┌─────────────────────────────────────────┐
29
- │ VibeSort::Sorter
31
+ │ VibeSort::Sorter (dispatcher)
32
+ │ - Picks the provider adapter │
33
+ └─────────────────┬───────────────────────┘
34
+
35
+
36
+ ┌─────────────────────────────────────────┐
37
+ │ VibeSort::Providers::Base │
38
+ │ - Shared prompt │
30
39
  │ - HTTP client (Faraday) │
31
- │ - Request building
32
- │ - Response parsing │
33
- - Validation
40
+ │ - Response parsing & validation
41
+ ├─────────────────────────────────────────┤
42
+ OpenAI Anthropic │ Gemini │ │
43
+ │ Groq │ SpaceXAI │
44
+ │ (request/response wire formats) │
34
45
  └─────────────────┬───────────────────────┘
35
46
 
36
47
 
37
48
  ┌─────────────────────────────────────────┐
38
- OpenAI API
39
- https://api.openai.com/v1/chat/
40
- completions
49
+ Provider API (HTTPS)
50
+ │ api.openai.com api.anthropic.com │
51
+ generativelanguage.googleapis.com
52
+ │ api.groq.com │ api.x.ai │
41
53
  └─────────────────────────────────────────┘
42
54
  ```
43
55
 
@@ -55,7 +67,7 @@ VibeSort follows a layered architecture with clear separation of concerns:
55
67
  - Return standardized response hashes
56
68
 
57
69
  **Key Methods**:
58
- - `initialize(api_key:, temperature: 0.0)`: Creates client with configuration
70
+ - `initialize(api_key:, temperature: 0.0, provider: :openai, model: nil)`: Creates client with configuration
59
71
  - `sort(array)`: Sorts array and returns result hash
60
72
 
61
73
  **Return Format**:
@@ -72,41 +84,46 @@ VibeSort follows a layered architecture with clear separation of concerns:
72
84
  **Purpose**: Encapsulates configuration settings.
73
85
 
74
86
  **Responsibilities**:
75
- - Store API key securely
76
- - Store temperature setting
77
- - Validate API key presence
87
+ - Store provider selection and API key
88
+ - Store model override and temperature setting
89
+ - Validate API key presence and provider name
78
90
 
79
91
  **Key Methods**:
80
- - `initialize(api_key:, temperature:)`: Creates configuration
81
- - Raises `ArgumentError` if API key is nil or empty
92
+ - `initialize(api_key:, temperature: 0.0, provider: :openai, model: nil)`: Creates configuration
93
+ - Raises `ArgumentError` if API key is nil/empty or provider is unknown
82
94
 
83
95
  **Attributes**:
84
- - `api_key`: OpenAI API key (String)
85
- - `temperature`: Model temperature (Float, 0.0-2.0)
96
+ - `api_key`: Provider API key (String)
97
+ - `provider`: `:openai`, `:anthropic`, `:gemini`, `:groq`, or `:spacexai` (Symbol)
98
+ - `model`: Model ID override, or nil for the provider default (String or nil)
99
+ - `temperature`: Model temperature (Float, 0.0-2.0; not sent to Anthropic)
86
100
 
87
101
  ### VibeSort::Sorter
88
102
 
89
- **Purpose**: Handles communication with OpenAI API.
90
-
91
- **Responsibilities**:
92
- - Build HTTP connection with Faraday
93
- - Construct API request payload
94
- - Send POST request to OpenAI
95
- - Parse and validate JSON responses
96
- - Extract sorted array from response
97
- - Raise `ApiError` on failures
103
+ **Purpose**: Dispatches the sort to the configured provider adapter.
98
104
 
99
105
  **Key Methods**:
100
106
  - `initialize(config)`: Creates sorter with configuration
101
- - `perform(array)`: Executes sort via API
102
- - `build_payload(array)`: Private - constructs request
103
- - `handle_response(response)`: Private - processes response
104
- - `parse_sorted_array(response)`: Private - extracts result
105
- - `validate_sorted_array!(array)`: Private - validates output
107
+ - `perform(array)`: Looks up the adapter in `PROVIDER_CLASSES` and delegates
106
108
 
107
- **Constants**:
108
- - `OPENAI_API_URL`: API endpoint
109
- - `DEFAULT_MODEL`: "gpt-3.5-turbo-1106" (supports JSON mode)
109
+ ### VibeSort::Providers
110
+
111
+ **Purpose**: One adapter per LLM provider, all sharing a common base.
112
+
113
+ **`Providers::Base` responsibilities**:
114
+ - Hold the shared sorting prompt
115
+ - Build the HTTP connection with Faraday
116
+ - Parse and validate JSON responses (shared across providers)
117
+ - Raise `ApiError` on failures
118
+
119
+ **Adapter hooks** (implemented per provider): `provider_name`, `endpoint`, `headers`, `build_payload`, `extract_content`
120
+
121
+ **Adapters and default models**:
122
+ - `Providers::OpenAI`: Chat Completions, `gpt-4o-mini`
123
+ - `Providers::Anthropic`: Messages API with structured outputs (JSON schema), `claude-opus-4-8`
124
+ - `Providers::Gemini`: generateContent with JSON response mode, `gemini-2.5-flash`
125
+ - `Providers::Groq`: OpenAI-compatible (subclasses `Providers::OpenAI`), `llama-3.3-70b-versatile`
126
+ - `Providers::SpaceXAI`: OpenAI-compatible (subclasses `Providers::OpenAI`), `grok-4`
110
127
 
111
128
  ### VibeSort::ApiError
112
129
 
@@ -132,12 +149,12 @@ VibeSort follows a layered architecture with clear separation of concerns:
132
149
 
133
150
  3. **Client creates Sorter**
134
151
  - Passes Configuration object
135
- - Sorter initializes Faraday connection
152
+ - Sorter picks the provider adapter, which initializes a Faraday connection
136
153
 
137
- 4. **Sorter builds request payload**
154
+ 4. **Adapter builds the provider-specific request payload** (OpenAI example)
138
155
  ```json
139
156
  {
140
- "model": "gpt-3.5-turbo-1106",
157
+ "model": "gpt-4o-mini",
141
158
  "temperature": 0.0,
142
159
  "response_format": { "type": "json_object" },
143
160
  "messages": [
@@ -153,16 +170,16 @@ VibeSort follows a layered architecture with clear separation of concerns:
153
170
  }
154
171
  ```
155
172
 
156
- 5. **Sorter sends POST request**
157
- - URL: `https://api.openai.com/v1/chat/completions`
158
- - Headers: Authorization (Bearer token), Content-Type
173
+ 5. **Adapter sends POST request**
174
+ - URL: the adapter's endpoint (e.g. `https://api.openai.com/v1/chat/completions`)
175
+ - Headers: provider auth (Bearer token, `x-api-key`, or `x-goog-api-key`), Content-Type
159
176
  - Body: JSON payload
160
177
 
161
- 6. **OpenAI processes request**
178
+ 6. **Provider processes request**
162
179
  - Model analyzes the array
163
180
  - Returns JSON with sorted array
164
181
 
165
- 7. **Sorter parses response**
182
+ 7. **Adapter parses response** (OpenAI example)
166
183
  ```json
167
184
  {
168
185
  "choices": [{
@@ -227,8 +244,7 @@ VibeSort follows a layered architecture with clear separation of concerns:
227
244
  ## Dependencies
228
245
 
229
246
  ### Runtime
230
- - **faraday** (~> 2.0): HTTP client library
231
- - **faraday-json** (~> 1.0): JSON middleware for Faraday
247
+ - **faraday** (~> 2.0): HTTP client library, the only runtime dependency; all providers are called over plain HTTPS
232
248
 
233
249
  ### Development
234
250
  - **rspec** (~> 3.0): Testing framework
@@ -236,8 +252,11 @@ VibeSort follows a layered architecture with clear separation of concerns:
236
252
 
237
253
  ## Design Decisions
238
254
 
239
- ### Why JSON Mode?
240
- OpenAI's JSON mode (`response_format: { type: "json_object" }`) ensures the model always returns valid JSON, making parsing more reliable.
255
+ ### Why JSON Mode / Structured Outputs?
256
+ Each adapter uses the strongest JSON guarantee its provider offers: OpenAI-compatible providers use JSON mode (`response_format: { type: "json_object" }`), Anthropic uses structured outputs with a JSON schema, and Gemini uses `responseMimeType: "application/json"`. This makes parsing reliable across providers.
257
+
258
+ ### Why Raw HTTP Instead of Provider SDKs?
259
+ Three simple JSON POSTs don't justify three SDK dependencies. Keeping everything on Faraday keeps the gem lightweight and the adapters symmetric.
241
260
 
242
261
  ### Why Temperature 0.0 by Default?
243
262
  Lower temperature (0.0) produces deterministic, consistent results. Sorting should be predictable, not creative!
@@ -312,8 +331,7 @@ Potential improvements for future versions:
312
331
 
313
332
  1. **Batch Sorting**: Sort multiple arrays in one API call
314
333
  2. **Caching**: Cache results for identical inputs
315
- 3. **Custom Models**: Allow users to specify different GPT models
316
- 4. **Retry Logic**: Automatic retry on transient failures
334
+ 3. **Retry Logic**: Automatic retry on transient failures
317
335
  5. **Async Support**: Non-blocking API calls with callbacks
318
336
  6. **Metrics**: Track API usage, costs, and performance
319
337
  7. **Different Sort Orders**: Support descending order
data/docs/development.md CHANGED
@@ -521,8 +521,8 @@ Document all public methods:
521
521
  # @return [Hash] Result hash with :success, :sorted_array, :error keys
522
522
  #
523
523
  # @example
524
- # client.sort([5, 2, 8])
525
- # # => { success: true, sorted_array: [2, 5, 8] }
524
+ # client.sort([5, 2, 8])
525
+ # # => { success: true, sorted_array: [2, 5, 8] }
526
526
  def sort(array)
527
527
  # ...
528
528
  end
@@ -563,4 +563,4 @@ Before submitting a PR:
563
563
  - Read the documentation
564
564
  - Ask in the community
565
565
 
566
- Happy coding! 🚀
566
+ Happy coding!
@@ -6,23 +6,23 @@ VibeSort has been updated to **version 0.2.0** with support for sorting arrays c
6
6
 
7
7
  ---
8
8
 
9
- ## 🎯 What Changed
9
+ ## What Changed
10
10
 
11
11
  ### Core Functionality
12
12
 
13
13
  #### Before (v0.1.0)
14
- -Sort arrays of numbers (integers and floats)
15
- -Strings not supported
16
- -Mixed-type arrays rejected
14
+ - Sort arrays of numbers (integers and floats)
15
+ - Strings not supported
16
+ - Mixed-type arrays rejected
17
17
 
18
18
  #### After (v0.2.0)
19
- -Sort arrays of numbers (integers and floats)
20
- -Sort arrays of strings (case-sensitive)
21
- -Sort mixed-type arrays (numbers + strings)
19
+ - Sort arrays of numbers (integers and floats)
20
+ - Sort arrays of strings (case-sensitive)
21
+ - Sort mixed-type arrays (numbers + strings)
22
22
 
23
23
  ---
24
24
 
25
- ## 📝 Technical Changes
25
+ ## Technical Changes
26
26
 
27
27
  ### 1. Input Validation (`VibeSort::Client`)
28
28
 
@@ -114,7 +114,7 @@ end
114
114
 
115
115
  ---
116
116
 
117
- ## 🚀 New Usage Examples
117
+ ## New Usage Examples
118
118
 
119
119
  ### Sorting Strings
120
120
 
@@ -141,24 +141,24 @@ puts result[:sorted_array]
141
141
 
142
142
  ---
143
143
 
144
- ## 📋 Sorting Rules
144
+ ## Sorting Rules
145
145
 
146
146
  The AI follows these standard sorting conventions:
147
147
 
148
148
  1. **Numbers Only**: Ascending numerical order
149
- - `[5, 2, 8, 1]``[1, 2, 5, 8]`
149
+ - `[5, 2, 8, 1]` `[1, 2, 5, 8]`
150
150
 
151
151
  2. **Strings Only**: Ascending alphabetical order (case-sensitive)
152
- - `["banana", "Apple", "cherry"]``["Apple", "banana", "cherry"]`
152
+ - `["banana", "Apple", "cherry"]` `["Apple", "banana", "cherry"]`
153
153
  - Capital letters come before lowercase in ASCII ordering
154
154
 
155
155
  3. **Mixed Types**: Numbers first, then strings
156
- - `[42, "hello", 8, "world"]``[8, 42, "hello", "world"]`
156
+ - `[42, "hello", 8, "world"]` `[8, 42, "hello", "world"]`
157
157
  - Each group is sorted within itself
158
158
 
159
159
  ---
160
160
 
161
- ## 📚 Documentation Updates
161
+ ## Documentation Updates
162
162
 
163
163
  ### Updated Files
164
164
 
@@ -185,7 +185,7 @@ The AI follows these standard sorting conventions:
185
185
 
186
186
  ---
187
187
 
188
- ## Backward Compatibility
188
+ ## Backward Compatibility
189
189
 
190
190
  **Good News:** This update is **fully backward compatible**!
191
191
 
@@ -203,7 +203,7 @@ result = client.sort([5, 2, 8, 1, 9])
203
203
 
204
204
  ---
205
205
 
206
- ## 🧪 Testing Recommendations
206
+ ## Testing Recommendations
207
207
 
208
208
  When upgrading to v0.2.0, test these scenarios:
209
209
 
@@ -237,7 +237,7 @@ client.sort([1, { key: "value" }]) # Contains hash
237
237
 
238
238
  ---
239
239
 
240
- ## 🔍 Implementation Notes
240
+ ## Implementation Notes
241
241
 
242
242
  ### Why These Changes?
243
243
 
@@ -263,27 +263,27 @@ The OpenAI GPT model (gpt-3.5-turbo-1106) handles mixed-type sorting intelligent
263
263
 
264
264
  ---
265
265
 
266
- ## 🎨 Architecture Remains Clean
266
+ ## Architecture Remains Clean
267
267
 
268
268
  The core architecture is unchanged:
269
269
 
270
270
  ```
271
271
  User Application
272
-
272
+
273
273
  VibeSort::Client (validates input)
274
-
274
+
275
275
  VibeSort::Configuration (stores settings)
276
-
276
+
277
277
  VibeSort::Sorter (communicates with OpenAI)
278
-
278
+
279
279
  OpenAI API (processes request)
280
-
280
+
281
281
  Sorted Array (returned to user)
282
282
  ```
283
283
 
284
284
  ---
285
285
 
286
- ## 📦 Upgrade Instructions
286
+ ## Upgrade Instructions
287
287
 
288
288
  ### Using Bundler
289
289
 
@@ -307,7 +307,7 @@ gem install vibe-sort -v 0.2.0
307
307
 
308
308
  ---
309
309
 
310
- ## 🐛 Known Limitations
310
+ ## Known Limitations
311
311
 
312
312
  Same limitations as v0.1.0:
313
313
 
@@ -326,7 +326,7 @@ Same limitations as v0.1.0:
326
326
 
327
327
  ---
328
328
 
329
- ## 🔮 Future Enhancements
329
+ ## Future Enhancements
330
330
 
331
331
  Potential features for future versions:
332
332
 
@@ -348,27 +348,27 @@ Potential features for future versions:
348
348
 
349
349
  ---
350
350
 
351
- ## 📞 Support
351
+ ## Support
352
352
 
353
- - 🐛 [Report Issues](https://github.com/chayut/vibe-sort/issues)
354
- - 💡 [Feature Requests](https://github.com/chayut/vibe-sort/issues/new?labels=enhancement)
355
- - 📖 [Documentation](https://github.com/chayut/vibe-sort/tree/main/docs)
353
+ - [Report Issues](https://github.com/chayut/vibe-sort/issues)
354
+ - [Feature Requests](https://github.com/chayut/vibe-sort/issues/new?labels=enhancement)
355
+ - [Documentation](https://github.com/chayut/vibe-sort/tree/main/docs)
356
356
 
357
357
  ---
358
358
 
359
- ## Summary
359
+ ## Summary
360
360
 
361
361
  Version 0.2.0 expands VibeSort's capabilities while maintaining:
362
362
 
363
- -Same clean API
364
- -Same architecture
365
- -Full backward compatibility
366
- -Same performance characteristics
367
- -Comprehensive documentation
363
+ - Same clean API
364
+ - Same architecture
365
+ - Full backward compatibility
366
+ - Same performance characteristics
367
+ - Comprehensive documentation
368
368
 
369
369
  The gem now handles a wider variety of data types, making it more versatile for educational purposes and demonstrations.
370
370
 
371
- **Happy Sorting!** 🌀
371
+ **Happy Sorting!**
372
372
 
373
373
  ---
374
374
 
data/lib/vibe/sort.rb CHANGED
@@ -1,10 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "sort/version"
4
-
5
- module Vibe
6
- module Sort
7
- class Error < StandardError; end
8
- # Your code goes here...
9
- end
10
- end
3
+ # Compatibility shim: Bundler autorequires "vibe/sort" for a gem named
4
+ # "vibe-sort", so `gem "vibe-sort"` in a Gemfile loads the real library
5
+ # without needing an explicit `require "vibe_sort"`.
6
+ require_relative "../vibe_sort"
@@ -7,17 +7,26 @@ module VibeSort
7
7
 
8
8
  # Initialize a new VibeSort client
9
9
  #
10
- # @param api_key [String] OpenAI API key
11
- # @param temperature [Float] Temperature for the model (default: 0.0)
12
- # @raise [ArgumentError] if api_key is invalid
10
+ # @param api_key [String] API key for the selected provider
11
+ # @param temperature [Float] Temperature for the model (default: 0.0).
12
+ # Ignored by providers whose current models do not accept it (Anthropic).
13
+ # @param provider [Symbol, String] LLM provider: :openai (default), :anthropic, or :gemini
14
+ # @param model [String, nil] Model ID override (nil uses the provider's default)
15
+ # @raise [ArgumentError] if api_key or provider is invalid
13
16
  #
14
- # @example
17
+ # @example OpenAI (default provider)
15
18
  # client = VibeSort::Client.new(api_key: ENV['OPENAI_API_KEY'])
16
- def initialize(api_key:, temperature: 0.0)
17
- @config = Configuration.new(api_key: api_key, temperature: temperature)
19
+ #
20
+ # @example Anthropic Claude
21
+ # client = VibeSort::Client.new(provider: :anthropic, api_key: ENV['ANTHROPIC_API_KEY'])
22
+ #
23
+ # @example Google Gemini with a custom model
24
+ # client = VibeSort::Client.new(provider: :gemini, api_key: ENV['GEMINI_API_KEY'], model: 'gemini-2.5-pro')
25
+ def initialize(api_key:, temperature: 0.0, provider: :openai, model: nil)
26
+ @config = Configuration.new(api_key: api_key, temperature: temperature, provider: provider, model: model)
18
27
  end
19
28
 
20
- # Sort an array of numbers and/or strings using OpenAI API
29
+ # Sort an array of numbers and/or strings using the configured provider's API
21
30
  #
22
31
  # @param array [Array] Array of numbers and/or strings to sort
23
32
  # @return [Hash] Result hash with keys:
@@ -44,6 +53,7 @@ module VibeSort
44
53
  # @example API error
45
54
  # result = client.sort([1, 2, 3]) # with invalid API key
46
55
  # #=> { success: false, sorted_array: [], error: "OpenAI API error: Invalid API key" }
56
+ # # The error prefix names the configured provider (OpenAI, Anthropic, or Gemini)
47
57
  def sort(array)
48
58
  # Validate input
49
59
  unless valid_input?(array)