vibe-sort 0.2.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.
@@ -0,0 +1,320 @@
1
+ # Architecture Overview
2
+
3
+ ## System Design
4
+
5
+ VibeSort follows a layered architecture with clear separation of concerns:
6
+
7
+ ```
8
+ ┌─────────────────────────────────────────┐
9
+ │ User Application │
10
+ └─────────────────┬───────────────────────┘
11
+
12
+
13
+ ┌─────────────────────────────────────────┐
14
+ │ VibeSort::Client (Public API) │
15
+ │ - Input validation │
16
+ │ - Error handling │
17
+ │ - Response formatting │
18
+ └─────────────────┬───────────────────────┘
19
+
20
+
21
+ ┌─────────────────────────────────────────┐
22
+ │ VibeSort::Configuration │
23
+ │ - API key management │
24
+ │ - Temperature settings │
25
+ └─────────────────┬───────────────────────┘
26
+
27
+
28
+ ┌─────────────────────────────────────────┐
29
+ │ VibeSort::Sorter │
30
+ │ - HTTP client (Faraday) │
31
+ │ - Request building │
32
+ │ - Response parsing │
33
+ │ - Validation │
34
+ └─────────────────┬───────────────────────┘
35
+
36
+
37
+ ┌─────────────────────────────────────────┐
38
+ │ OpenAI API │
39
+ │ https://api.openai.com/v1/chat/ │
40
+ │ completions │
41
+ └─────────────────────────────────────────┘
42
+ ```
43
+
44
+ ## Component Details
45
+
46
+ ### VibeSort::Client
47
+
48
+ **Purpose**: Public-facing interface that users interact with.
49
+
50
+ **Responsibilities**:
51
+ - Initialize configuration
52
+ - Validate input arrays (must be non-empty arrays of numbers)
53
+ - Delegate sorting to `Sorter`
54
+ - Catch and format exceptions
55
+ - Return standardized response hashes
56
+
57
+ **Key Methods**:
58
+ - `initialize(api_key:, temperature: 0.0)`: Creates client with configuration
59
+ - `sort(array)`: Sorts array and returns result hash
60
+
61
+ **Return Format**:
62
+ ```ruby
63
+ {
64
+ success: Boolean,
65
+ sorted_array: Array<Numeric>,
66
+ error: String (only on failure)
67
+ }
68
+ ```
69
+
70
+ ### VibeSort::Configuration
71
+
72
+ **Purpose**: Encapsulates configuration settings.
73
+
74
+ **Responsibilities**:
75
+ - Store API key securely
76
+ - Store temperature setting
77
+ - Validate API key presence
78
+
79
+ **Key Methods**:
80
+ - `initialize(api_key:, temperature:)`: Creates configuration
81
+ - Raises `ArgumentError` if API key is nil or empty
82
+
83
+ **Attributes**:
84
+ - `api_key`: OpenAI API key (String)
85
+ - `temperature`: Model temperature (Float, 0.0-2.0)
86
+
87
+ ### VibeSort::Sorter
88
+
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
98
+
99
+ **Key Methods**:
100
+ - `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
106
+
107
+ **Constants**:
108
+ - `OPENAI_API_URL`: API endpoint
109
+ - `DEFAULT_MODEL`: "gpt-3.5-turbo-1106" (supports JSON mode)
110
+
111
+ ### VibeSort::ApiError
112
+
113
+ **Purpose**: Custom exception for API-related errors.
114
+
115
+ **Responsibilities**:
116
+ - Encapsulate error message
117
+ - Store HTTP response for debugging
118
+ - Provide clear error context
119
+
120
+ **Attributes**:
121
+ - `message`: Error description (String)
122
+ - `response`: Faraday::Response object (optional)
123
+
124
+ ## Request Flow
125
+
126
+ 1. **User calls `client.sort([34, 1, 99, 15, 8])`**
127
+
128
+ 2. **Client validates input**
129
+ - Checks if input is an Array
130
+ - Checks if all elements are Numeric
131
+ - Returns error hash if invalid
132
+
133
+ 3. **Client creates Sorter**
134
+ - Passes Configuration object
135
+ - Sorter initializes Faraday connection
136
+
137
+ 4. **Sorter builds request payload**
138
+ ```json
139
+ {
140
+ "model": "gpt-3.5-turbo-1106",
141
+ "temperature": 0.0,
142
+ "response_format": { "type": "json_object" },
143
+ "messages": [
144
+ {
145
+ "role": "system",
146
+ "content": "You are an assistant that only sorts..."
147
+ },
148
+ {
149
+ "role": "user",
150
+ "content": "Please sort this array: [34,1,99,15,8]"
151
+ }
152
+ ]
153
+ }
154
+ ```
155
+
156
+ 5. **Sorter sends POST request**
157
+ - URL: `https://api.openai.com/v1/chat/completions`
158
+ - Headers: Authorization (Bearer token), Content-Type
159
+ - Body: JSON payload
160
+
161
+ 6. **OpenAI processes request**
162
+ - Model analyzes the array
163
+ - Returns JSON with sorted array
164
+
165
+ 7. **Sorter parses response**
166
+ ```json
167
+ {
168
+ "choices": [{
169
+ "message": {
170
+ "content": "{\"sorted_array\": [1,8,15,34,99]}"
171
+ }
172
+ }]
173
+ }
174
+ ```
175
+
176
+ 8. **Sorter validates result**
177
+ - Checks if `sorted_array` key exists
178
+ - Validates all elements are Numeric
179
+ - Raises `ApiError` if invalid
180
+
181
+ 9. **Client returns success hash**
182
+ ```ruby
183
+ {
184
+ success: true,
185
+ sorted_array: [1, 8, 15, 34, 99]
186
+ }
187
+ ```
188
+
189
+ ## Error Handling
190
+
191
+ ### Input Validation Errors
192
+ ```ruby
193
+ # Empty array
194
+ { success: false, sorted_array: [], error: "Input must be an array of numbers" }
195
+
196
+ # Non-array input
197
+ { success: false, sorted_array: [], error: "Input must be an array of numbers" }
198
+
199
+ # Mixed types
200
+ { success: false, sorted_array: [], error: "Input must be an array of numbers" }
201
+ ```
202
+
203
+ ### API Errors
204
+ ```ruby
205
+ # Invalid API key
206
+ { success: false, sorted_array: [], error: "OpenAI API error: Invalid API key" }
207
+
208
+ # Rate limit
209
+ { success: false, sorted_array: [], error: "OpenAI API error: Rate limit exceeded" }
210
+
211
+ # Network error
212
+ { success: false, sorted_array: [], error: "Unexpected error: Connection failed" }
213
+ ```
214
+
215
+ ### Response Parsing Errors
216
+ ```ruby
217
+ # Invalid JSON
218
+ { success: false, sorted_array: [], error: "Failed to parse JSON response: ..." }
219
+
220
+ # Missing sorted_array key
221
+ { success: false, sorted_array: [], error: "Response does not contain a valid 'sorted_array'" }
222
+
223
+ # Non-numeric values
224
+ { success: false, sorted_array: [], error: "Sorted array contains non-numeric values" }
225
+ ```
226
+
227
+ ## Dependencies
228
+
229
+ ### Runtime
230
+ - **faraday** (~> 2.0): HTTP client library
231
+ - **faraday-json** (~> 1.0): JSON middleware for Faraday
232
+
233
+ ### Development
234
+ - **rspec** (~> 3.0): Testing framework
235
+ - **pry** (~> 0.14): Debugging console
236
+
237
+ ## Design Decisions
238
+
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.
241
+
242
+ ### Why Temperature 0.0 by Default?
243
+ Lower temperature (0.0) produces deterministic, consistent results. Sorting should be predictable, not creative!
244
+
245
+ ### Why Faraday?
246
+ Faraday is a flexible, well-maintained HTTP client with middleware support, making it easy to add JSON encoding/decoding.
247
+
248
+ ### Why Separate Client and Sorter?
249
+ Separation of concerns:
250
+ - **Client**: User-facing API, input validation, error formatting
251
+ - **Sorter**: HTTP communication, response parsing, API logic
252
+
253
+ This makes testing easier and keeps responsibilities clear.
254
+
255
+ ## Testing Strategy
256
+
257
+ ### Unit Tests
258
+ - Test each class in isolation
259
+ - Mock HTTP requests (use WebMock or VCR)
260
+ - Test error conditions
261
+ - Validate input/output formats
262
+
263
+ ### Integration Tests
264
+ - Test full flow with real API (use test API key)
265
+ - Verify correct request format
266
+ - Verify response parsing
267
+ - Test various array sizes
268
+
269
+ ### Edge Cases
270
+ - Empty arrays
271
+ - Single-element arrays
272
+ - Already sorted arrays
273
+ - Reverse-sorted arrays
274
+ - Duplicate values
275
+ - Negative numbers
276
+ - Floating-point numbers
277
+ - Very large numbers
278
+
279
+ ## Security Considerations
280
+
281
+ 1. **API Key Storage**: Never hardcode API keys. Use environment variables.
282
+ 2. **Input Validation**: Always validate user input before sending to API.
283
+ 3. **Output Validation**: Verify API responses before returning to user.
284
+ 4. **Error Messages**: Don't expose sensitive information in error messages.
285
+ 5. **HTTPS**: All API communication uses HTTPS (encrypted).
286
+
287
+ ## Performance Considerations
288
+
289
+ ### Latency
290
+ - Each sort requires an API round-trip (~1-3 seconds)
291
+ - Network latency varies by location
292
+ - OpenAI API processing time varies by load
293
+
294
+ ### Cost
295
+ - OpenAI charges per token
296
+ - Each sort uses approximately 100-200 tokens
297
+ - Cost: ~$0.001-0.002 per sort (with gpt-3.5-turbo)
298
+
299
+ ### Rate Limits
300
+ - OpenAI enforces rate limits (requests per minute)
301
+ - Free tier: 3 requests/minute
302
+ - Paid tier: 60+ requests/minute
303
+
304
+ ### Scalability
305
+ - Not suitable for high-frequency sorting
306
+ - Consider batching if sorting multiple arrays
307
+ - Add caching if sorting same arrays repeatedly
308
+
309
+ ## Future Enhancements
310
+
311
+ Potential improvements for future versions:
312
+
313
+ 1. **Batch Sorting**: Sort multiple arrays in one API call
314
+ 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
317
+ 5. **Async Support**: Non-blocking API calls with callbacks
318
+ 6. **Metrics**: Track API usage, costs, and performance
319
+ 7. **Different Sort Orders**: Support descending order
320
+ 8. **Custom Sorting**: Allow custom comparison functions