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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +91 -42
- data/docs/IMPLEMENTATION_PLAN.md +50 -50
- data/docs/README.md +20 -20
- data/docs/api_reference.md +68 -28
- data/docs/architecture.md +64 -46
- data/docs/development.md +3 -3
- data/docs/v0.2.0_UPDATE.md +37 -37
- data/lib/vibe/sort.rb +4 -8
- data/lib/vibe_sort/client.rb +17 -7
- data/lib/vibe_sort/configuration.rb +15 -6
- data/lib/vibe_sort/providers/anthropic.rb +68 -0
- data/lib/vibe_sort/providers/base.rb +147 -0
- data/lib/vibe_sort/providers/gemini.rb +43 -0
- data/lib/vibe_sort/providers/groq.rb +21 -0
- data/lib/vibe_sort/providers/openai.rb +41 -0
- data/lib/vibe_sort/providers/space_x_ai.rb +21 -0
- data/lib/vibe_sort/sorter.rb +10 -103
- data/lib/vibe_sort/version.rb +1 -1
- data/lib/vibe_sort.rb +6 -0
- metadata +17 -8
- data/lib/vibe/sort/version.rb +0 -7
- data/sig/vibe/sort.rbs +0 -6
data/docs/api_reference.md
CHANGED
|
@@ -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):
|
|
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
|
|
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):
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
#### `
|
|
198
|
+
#### `PROVIDER_CLASSES`
|
|
199
|
+
|
|
200
|
+
Maps provider symbols to adapter classes.
|
|
201
|
+
|
|
202
|
+
**Value:** `{ openai:, anthropic:, gemini:, groq:, spacexai: }`
|
|
203
|
+
|
|
204
|
+
---
|
|
174
205
|
|
|
175
|
-
|
|
206
|
+
## VibeSort::Providers
|
|
176
207
|
|
|
177
|
-
|
|
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
|
-
|
|
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
|
-
|
|
218
|
+
Notes:
|
|
182
219
|
|
|
183
|
-
|
|
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
|
-
| "
|
|
275
|
-
| "
|
|
276
|
-
| "
|
|
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
|
-
|
|
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.
|
|
475
|
+
Current version: `0.3.0`
|
|
436
476
|
|
|
437
477
|
```ruby
|
|
438
478
|
VibeSort::VERSION
|
|
439
|
-
# => "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
|
-
│ -
|
|
32
|
-
|
|
33
|
-
│
|
|
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
|
-
│
|
|
39
|
-
│
|
|
40
|
-
│
|
|
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
|
|
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
|
|
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`:
|
|
85
|
-
- `
|
|
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**:
|
|
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)`:
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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. **
|
|
154
|
+
4. **Adapter builds the provider-specific request payload** (OpenAI example)
|
|
138
155
|
```json
|
|
139
156
|
{
|
|
140
|
-
"model": "gpt-
|
|
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. **
|
|
157
|
-
- URL: `https://api.openai.com/v1/chat/completions`
|
|
158
|
-
- Headers:
|
|
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. **
|
|
178
|
+
6. **Provider processes request**
|
|
162
179
|
- Model analyzes the array
|
|
163
180
|
- Returns JSON with sorted array
|
|
164
181
|
|
|
165
|
-
7. **
|
|
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
|
|
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. **
|
|
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
|
-
#
|
|
525
|
-
#
|
|
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!
|
data/docs/v0.2.0_UPDATE.md
CHANGED
|
@@ -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
|
-
##
|
|
9
|
+
## What Changed
|
|
10
10
|
|
|
11
11
|
### Core Functionality
|
|
12
12
|
|
|
13
13
|
#### Before (v0.1.0)
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
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
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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]`
|
|
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"]`
|
|
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"]`
|
|
156
|
+
- `[42, "hello", 8, "world"]` `[8, 42, "hello", "world"]`
|
|
157
157
|
- Each group is sorted within itself
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
161
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
351
|
+
## Support
|
|
352
352
|
|
|
353
|
-
-
|
|
354
|
-
-
|
|
355
|
-
-
|
|
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
|
-
##
|
|
359
|
+
## Summary
|
|
360
360
|
|
|
361
361
|
Version 0.2.0 expands VibeSort's capabilities while maintaining:
|
|
362
362
|
|
|
363
|
-
-
|
|
364
|
-
-
|
|
365
|
-
-
|
|
366
|
-
-
|
|
367
|
-
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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"
|
data/lib/vibe_sort/client.rb
CHANGED
|
@@ -7,17 +7,26 @@ module VibeSort
|
|
|
7
7
|
|
|
8
8
|
# Initialize a new VibeSort client
|
|
9
9
|
#
|
|
10
|
-
# @param api_key [String]
|
|
11
|
-
# @param temperature [Float] Temperature for the model (default: 0.0)
|
|
12
|
-
#
|
|
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
|
-
|
|
17
|
-
|
|
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
|
|
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)
|