coolhand 0.1.5 โ†’ 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04f5762e1c9b3dad57c3b65fbe6860a0394fd793f49e67538eaf8c68584ccae5
4
- data.tar.gz: d666c068c33af71f895228030d6342008ccdae290de4c603dec687cf07b5645d
3
+ metadata.gz: fc0fc356a6cf69d4a0c67a906000cab9590d9fc2a452efec8037a7f541efa561
4
+ data.tar.gz: ec6f7a136ae1d8e139bf638175b81a2dda063b9bf19d0199ab7f7135cf6d833d
5
5
  SHA512:
6
- metadata.gz: 4a9de9973617ef1a0816811a5d29dc43ebdda8eb11540474d15e350670a675f4826ff6d9eac56aad5e82dbebdeb50a812ab8bc96d8a16a9f522d27294e6f8035
7
- data.tar.gz: 382033854564a57ced160afad00bec423d551a2aaeda70a69cfc9a1a2eaf83843dfe6c3479ca3733ff71a436516032a06c0d1b7dc7f8bc937bd49e5376f51049
6
+ metadata.gz: 131465dcaf94ae8cc4b5dce47252fe92effc9693ba4de6e61247714c682a717934fa3144cf3228bf754fe89a53803051f32a895c3a42fd3c07990d4cf74286a5
7
+ data.tar.gz: 26e03d0f27b9acbeb36ff6a0e0ee11cca55b8142cd17d494972013534ba4d8b3753b29fb3565dedb8c0f8daf1e26d7af443353999f5956f5b1b7b8d7ea139585
data/.rubocop.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  # This is the configuration used to check the rubocop source code.
2
2
 
3
- require:
3
+ plugins:
4
4
  - rubocop-performance
5
+ require:
5
6
  - rubocop-rspec
6
7
  inherit_gem:
7
8
  test-prof: config/rubocop-rspec.yml
data/CHANGELOG.md CHANGED
@@ -5,6 +5,52 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] - 2025-12-16
9
+
10
+ ### โœจ Major New Features
11
+ - **Official Anthropic Gem Support** - Added comprehensive monitoring support for the official `anthropic` gem (v1.8+) through direct Net::HTTP interception
12
+ - **Dual Gem Compatibility** - Support for both `anthropic` (official) and `ruby-anthropic` (community) gems with automatic detection and appropriate interceptor selection
13
+ - **Streaming Response Support** - Enhanced SSE (Server-Sent Events) parsing for Anthropic streaming responses with proper message accumulation and reconstruction
14
+ - **Graceful Gem Conflict Handling** - Automatic detection when both anthropic gems are installed, with graceful degradation to ruby-anthropic monitoring
15
+
16
+ ### ๐Ÿ—๏ธ Architecture Improvements
17
+ - **AnthropicInterceptor Module** - New dedicated interceptor for official anthropic gem requests with streaming response support
18
+ - **BaseInterceptor Module** - Shared functionality across interceptors with unified API logging format and DRY principles
19
+ - **Modular Design** - Moved from single `interceptor.rb` to specialized interceptors (`faraday_interceptor.rb`, `anthropic_interceptor.rb`)
20
+ - **Enhanced Configuration** - Automatic gem detection in `configure` block with appropriate interceptor selection
21
+
22
+ ### ๐Ÿ”ง API & Format Changes
23
+ - **Unified Logging Format** - Standardized API request/response logging with `raw_request` wrapper and collector data integration
24
+ - **Headers Field Update** - API logs now use `headers` instead of `request_headers` for consistency
25
+ - **Silent Mode Override** - Critical warnings (like gem conflicts) now always display regardless of silent mode settings
26
+
27
+ ### ๐Ÿงช Testing & Quality
28
+ - **Comprehensive Test Coverage** - Added 16 new specs covering all interceptor scenarios including gem conflict handling
29
+ - **RuboCop Compliance** - Applied linting with proper line length, verified doubles, and RSpec best practices
30
+ - **Thread Safety** - Enhanced request correlation with thread-local storage for streaming requests
31
+
32
+ ### ๐Ÿ—‚๏ธ Supported Environments
33
+ - **Development Environment** - Uses official `anthropic` gem for Net::HTTP-based requests
34
+ - **AR_Dev Environment** - Uses `ruby-anthropic` gem for Faraday-based requests
35
+ - **Automatic Detection** - Coolhand detects which gem is loaded and applies appropriate interception
36
+
37
+ ### ๐Ÿ’” Breaking Changes
38
+ - **Removed** - `lib/coolhand/ruby/interceptor.rb` replaced by specialized interceptor modules
39
+ - **API Change** - Logging format now uses `headers` field instead of `request_headers`
40
+
41
+ ### ๐Ÿ”„ Migration Guide
42
+ For users upgrading from v0.1.x:
43
+ - No code changes required for basic usage
44
+ - If depending on old `interceptor.rb` directly, update imports to use `faraday_interceptor.rb` or `anthropic_interceptor.rb`
45
+ - API log consumers should expect `headers` field instead of `request_headers`
46
+
47
+ ### ๐Ÿ“Š Compatibility Matrix
48
+ | Gem | Version | Interceptor | Status |
49
+ |-----|---------|-------------|--------|
50
+ | `anthropic` | 1.8+ | AnthropicInterceptor | โœ… Full Support |
51
+ | `ruby-anthropic` | 0.4+ | FaradayInterceptor | โœ… Full Support |
52
+ | Both gems | Any | FaradayInterceptor | โš ๏ธ Graceful Degradation |
53
+
8
54
  ## [0.1.5] - 2024-12-09
9
55
 
10
56
  ### ๐Ÿ› Critical Bug Fixes
data/README.md CHANGED
@@ -186,29 +186,7 @@ puts response.dig("choices", 0, "message", "content")
186
186
  # The request and response have been automatically logged to Coolhand!
187
187
  ```
188
188
 
189
- ### With Anthropic Ruby Client
190
-
191
- ```ruby
192
- require 'anthropic'
193
- require 'coolhand/ruby'
194
-
195
- # Configure Coolhand
196
- Coolhand.configure do |config|
197
- config.api_key = 'your_api_key_here'
198
- end
199
-
200
- # Use Anthropic normally - requests are automatically logged
201
- anthropic = Anthropic::Client.new(access_token: ENV['ANTHROPIC_API_KEY'])
202
-
203
- response = anthropic.messages(
204
- model: "claude-3-opus",
205
- max_tokens: 1024,
206
- messages: [{ role: "user", content: "Hello, Claude!" }]
207
- )
208
-
209
- puts response["content"]
210
- # Automatically logged to Coolhand!
211
- ```
189
+ ๐Ÿ“– **[Complete Anthropic Integration Guide โ†’](docs/anthropic.md)** - Supports both official and community gems with automatic detection
212
190
 
213
191
  ## Logging Inbound Webhooks
214
192
 
@@ -285,23 +263,43 @@ The filtering is automatic and applies to all monitored API calls and webhook lo
285
263
 
286
264
  ## Supported Libraries
287
265
 
288
- The monitor works with any Ruby library that uses Faraday for HTTP(S) requests to LLM APIs, including:
266
+ The monitor works with multiple transport layers and Ruby libraries:
289
267
 
268
+ **Faraday-based libraries:**
290
269
  - OpenAI Ruby SDK
291
- - Anthropic Ruby SDK
270
+ - ruby-anthropic gem (community Anthropic gem)
292
271
  - ruby-openai gem
293
272
  - LangChain.rb
294
273
  - Direct Faraday requests
295
274
  - Any other Faraday-based HTTP client
296
275
 
276
+ **Native HTTP libraries:**
277
+ - Official Anthropic Ruby SDK (using Net::HTTP)
278
+ - Any library using Net::HTTP directly
279
+
280
+ **Auto-detection**: Coolhand automatically detects which transport layer your libraries use and applies the appropriate monitoring strategy.
281
+
297
282
  ## How It Works
298
283
 
299
- The gem patches Faraday connections to intercept HTTP requests. When a request matches the configured LLM endpoints:
284
+ Coolhand uses a dual-interceptor strategy to monitor different HTTP transport layers:
285
+
286
+ ### Faraday Interceptor
287
+ - Patches Faraday connections using middleware injection
288
+ - Monitors: OpenAI SDK, ruby-anthropic, LangChain.rb, and other Faraday-based libraries
289
+ - Handles: Standard HTTP requests and Server-Sent Events (SSE) for streaming
290
+
291
+ ### Anthropic Interceptor
292
+ - Patches the official Anthropic gem's internal HTTP transport (Net::HTTP)
293
+ - Monitors: Official Anthropic Ruby SDK requests
294
+
295
+ ### Request Flow
296
+ When a request matches configured LLM endpoints:
300
297
 
301
- 1. The original request executes normally
302
- 2. Request and response data (body, headers, status) are captured
303
- 3. Data is sent to the Coolhand API asynchronously in a background thread
304
- 4. Your application continues without any performance impact
298
+ 1. The original request executes normally with zero performance impact
299
+ 2. Request and response data (body, headers, status) are captured by the appropriate interceptor
300
+ 3. For streaming requests, the complete accumulated response is captured (not individual chunks)
301
+ 4. Data is sent to the Coolhand API asynchronously in a background thread
302
+ 5. Your application continues without interruption
305
303
 
306
304
  For non-matching endpoints, requests pass through unchanged.
307
305
 
@@ -369,6 +367,7 @@ The monitor handles errors gracefully:
369
367
 
370
368
  ## Integration Guides
371
369
 
370
+ - **[Anthropic Integration](docs/anthropic.md)** - Complete guide for both official and community Anthropic gems, including streaming, dual gem handling, and troubleshooting
372
371
  - **[ElevenLabs Integration](docs/elevenlabs.md)** - Complete guide for integrating ElevenLabs Conversational AI with webhook capture and feedback submission
373
372
 
374
373
  ## Security
data/docs/anthropic.md ADDED
@@ -0,0 +1,518 @@
1
+ # Anthropic Integration Guide
2
+
3
+ Coolhand provides comprehensive monitoring for Anthropic's Claude API through support for both the official and community Ruby gems. This guide covers setup, usage, streaming, and troubleshooting.
4
+
5
+ ## Overview
6
+
7
+ Coolhand automatically detects which Anthropic gem you're using and applies the appropriate monitoring strategy:
8
+
9
+ - **Official Anthropic Gem** (`anthropic`): Uses Net::HTTP transport, monitored via AnthropicInterceptor
10
+ - **Community Ruby-Anthropic Gem** (`ruby-anthropic`): Uses Faraday transport, monitored via FaradayInterceptor
11
+ - **Dual Installation**: Automatically handles conflicts and prevents duplicate logging
12
+
13
+ ## Quick Start
14
+
15
+ ### Basic Configuration
16
+
17
+ ```ruby
18
+ require 'coolhand/ruby'
19
+
20
+ Coolhand.configure do |config|
21
+ config.api_key = 'your_coolhand_api_key_here'
22
+ config.silent = true # Set to false for debug output
23
+ end
24
+ ```
25
+
26
+ That's it! All Anthropic API calls are now automatically monitored.
27
+
28
+ ## Official Anthropic Gem
29
+
30
+ ### Installation
31
+
32
+ ```bash
33
+ gem install anthropic
34
+ # or add to Gemfile
35
+ gem 'anthropic'
36
+ ```
37
+
38
+ ### Basic Usage
39
+
40
+ ```ruby
41
+ require 'anthropic'
42
+ require 'coolhand/ruby'
43
+
44
+ # Configure Coolhand
45
+ Coolhand.configure do |config|
46
+ config.api_key = 'your_coolhand_api_key'
47
+ end
48
+
49
+ # Use official Anthropic gem normally
50
+ client = Anthropic::Client.new
51
+
52
+ response = client.messages(
53
+ parameters: {
54
+ model: "claude-3-sonnet-20240229",
55
+ max_tokens: 1024,
56
+ messages: [{ role: "user", content: "Hello, Claude!" }]
57
+ }
58
+ )
59
+
60
+ puts response.content.first.text
61
+ # โœ… Request and response automatically logged to Coolhand
62
+ ```
63
+
64
+ ### Streaming with Official Gem
65
+
66
+ ```ruby
67
+ # Streaming is automatically detected and properly logged
68
+ response = client.messages(
69
+ parameters: {
70
+ model: "claude-3-sonnet-20240229",
71
+ max_tokens: 1024,
72
+ messages: [{ role: "user", content: "Write a haiku about Ruby" }],
73
+ stream: true # โœ… Streaming automatically detected
74
+ }
75
+ )
76
+
77
+ # Process streaming response
78
+ accumulated_text = ""
79
+ response.each do |chunk|
80
+ if chunk.delta&.text
81
+ print chunk.delta.text
82
+ accumulated_text += chunk.delta.text
83
+ end
84
+ end
85
+
86
+ # โœ… Complete accumulated response logged to Coolhand (not individual chunks)
87
+ ```
88
+
89
+ ### Advanced Configuration
90
+
91
+ ```ruby
92
+ client = Anthropic::Client.new
93
+
94
+ # All parameters are automatically captured and logged
95
+ response = client.messages(
96
+ parameters: {
97
+ model: "claude-3-opus-20240229",
98
+ max_tokens: 2000,
99
+ temperature: 0.7,
100
+ top_p: 0.9,
101
+ system: "You are a helpful assistant specializing in Ruby programming.",
102
+ messages: [
103
+ { role: "user", content: "Explain Ruby metaprogramming" }
104
+ ],
105
+ # Streaming works automatically
106
+ stream: true
107
+ }
108
+ )
109
+
110
+ # โœ… All parameters (model, temperature, top_p, system, etc.) logged
111
+ ```
112
+
113
+ ## Community Ruby-Anthropic Gem
114
+
115
+ ### Installation
116
+
117
+ ```bash
118
+ gem install ruby-anthropic
119
+ # or add to Gemfile
120
+ gem 'ruby-anthropic'
121
+ ```
122
+
123
+ ### Basic Usage
124
+
125
+ ```ruby
126
+ require 'ruby-anthropic'
127
+ require 'coolhand/ruby'
128
+
129
+ # Configure Coolhand
130
+ Coolhand.configure do |config|
131
+ config.api_key = 'your_coolhand_api_key'
132
+ end
133
+
134
+ # Use ruby-anthropic gem normally - monitored via Faraday
135
+ client = Anthropic::Client.new(access_token: ENV['ANTHROPIC_API_KEY'])
136
+
137
+ response = client.messages(
138
+ model: "claude-3-sonnet-20240229",
139
+ max_tokens: 1024,
140
+ messages: [{ role: "user", content: "Hello, Claude!" }]
141
+ )
142
+
143
+ puts response.dig("content", 0, "text")
144
+ # โœ… Automatically logged via FaradayInterceptor
145
+ ```
146
+
147
+ ### Streaming with Ruby-Anthropic
148
+
149
+ ```ruby
150
+ # Streaming works seamlessly via Faraday monitoring
151
+ response = client.messages(
152
+ model: "claude-3-sonnet-20240229",
153
+ max_tokens: 1024,
154
+ messages: [{ role: "user", content: "Count to 10 slowly" }],
155
+ stream: true
156
+ )
157
+
158
+ # Process Server-Sent Events
159
+ response.each do |event|
160
+ puts event if event.start_with?("data:")
161
+ end
162
+
163
+ # โœ… Complete conversation logged to Coolhand
164
+ ```
165
+
166
+ ## Dual Gem Installation
167
+
168
+ ### Automatic Conflict Resolution
169
+
170
+ When both gems are installed, Coolhand automatically handles the conflict:
171
+
172
+ ```ruby
173
+ require 'anthropic' # Official gem
174
+ require 'ruby-anthropic' # Community gem
175
+ require 'coolhand/ruby'
176
+
177
+ Coolhand.configure do |config|
178
+ config.api_key = 'your_coolhand_api_key'
179
+ end
180
+
181
+ # โš ๏ธ Warning displayed:
182
+ # "Both 'anthropic' and 'ruby-anthropic' gems are installed.
183
+ # Coolhand will only monitor ruby-anthropic (Faraday-based) requests.
184
+ # Official anthropic gem monitoring has been disabled."
185
+ ```
186
+
187
+ **Recommendation**: Use only one gem to avoid confusion. Choose based on your needs:
188
+ - **Official gem**: Latest features, official support, Net::HTTP transport
189
+ - **Community gem**: Faraday-based, may have community contributions
190
+
191
+ ### Manual Conflict Resolution
192
+
193
+ To explicitly use the official gem when both are installed:
194
+
195
+ ```ruby
196
+ # Temporarily hide the community gem
197
+ begin
198
+ # Remove ruby-anthropic from the load path
199
+ $LOAD_PATH.reject! { |path| path.include?('ruby-anthropic') }
200
+
201
+ require 'anthropic'
202
+ require 'coolhand/ruby'
203
+
204
+ Coolhand.configure do |config|
205
+ config.api_key = 'your_coolhand_api_key'
206
+ end
207
+
208
+ # Now only the official gem will be monitored
209
+ client = Anthropic::Client.new
210
+ # ... use official gem
211
+ end
212
+ ```
213
+
214
+ ## Rails Integration
215
+
216
+ ### Initializer Setup
217
+
218
+ ```ruby
219
+ # config/initializers/coolhand.rb
220
+ Coolhand.configure do |config|
221
+ # Use Rails credentials for API key
222
+ config.api_key = Rails.application.credentials.coolhand_api_key
223
+
224
+ # Suppress console output in production
225
+ config.silent = Rails.env.production?
226
+
227
+ # Ensure Anthropic endpoints are monitored (default behavior)
228
+ # config.intercept_addresses = ["api.openai.com", "api.anthropic.com"]
229
+ end
230
+ ```
231
+
232
+ ### Service Object Pattern
233
+
234
+ ```ruby
235
+ # app/services/claude_chat_service.rb
236
+ class ClaudeChatService
237
+ def initialize
238
+ @client = Anthropic::Client.new
239
+ end
240
+
241
+ def generate_response(user_message, context: nil)
242
+ messages = []
243
+ messages << { role: "system", content: context } if context
244
+ messages << { role: "user", content: user_message }
245
+
246
+ response = @client.messages(
247
+ parameters: {
248
+ model: "claude-3-sonnet-20240229",
249
+ max_tokens: 1500,
250
+ messages: messages
251
+ }
252
+ )
253
+
254
+ response.content.first.text
255
+ # โœ… Automatically logged to Coolhand with all context
256
+ end
257
+
258
+ def stream_response(user_message)
259
+ response = @client.messages(
260
+ parameters: {
261
+ model: "claude-3-sonnet-20240229",
262
+ max_tokens: 1500,
263
+ messages: [{ role: "user", content: user_message }],
264
+ stream: true
265
+ }
266
+ )
267
+
268
+ Enumerator.new do |yielder|
269
+ response.each do |chunk|
270
+ if chunk.delta&.text
271
+ yielder << chunk.delta.text
272
+ end
273
+ end
274
+ end
275
+ # โœ… Complete streaming conversation logged
276
+ end
277
+ end
278
+ ```
279
+
280
+ ### Background Job Example
281
+
282
+ ```ruby
283
+ # app/jobs/claude_analysis_job.rb
284
+ class ClaudeAnalysisJob < ApplicationJob
285
+ def perform(document_id, analysis_type)
286
+ document = Document.find(document_id)
287
+
288
+ client = Anthropic::Client.new
289
+
290
+ response = client.messages(
291
+ parameters: {
292
+ model: "claude-3-opus-20240229",
293
+ max_tokens: 2000,
294
+ system: "You are an expert document analyzer.",
295
+ messages: [
296
+ {
297
+ role: "user",
298
+ content: "Analyze this document: #{document.content}"
299
+ }
300
+ ]
301
+ }
302
+ )
303
+
304
+ document.update!(
305
+ analysis: response.content.first.text,
306
+ analysis_type: analysis_type
307
+ )
308
+
309
+ # โœ… Analysis request logged with document context
310
+ end
311
+ end
312
+ ```
313
+
314
+ ## Advanced Features
315
+
316
+ ### Thread-Safe Concurrent Requests
317
+
318
+ ```ruby
319
+ # Coolhand handles concurrent requests safely
320
+ threads = []
321
+
322
+ 10.times do |i|
323
+ threads << Thread.new do
324
+ client = Anthropic::Client.new
325
+
326
+ response = client.messages(
327
+ parameters: {
328
+ model: "claude-3-sonnet-20240229",
329
+ max_tokens: 500,
330
+ messages: [{ role: "user", content: "Request #{i}" }]
331
+ }
332
+ )
333
+
334
+ puts "Response #{i}: #{response.content.first.text}"
335
+ end
336
+ end
337
+
338
+ threads.each(&:join)
339
+ # โœ… All 10 requests logged correctly without conflicts
340
+ ```
341
+
342
+ ### Request Correlation
343
+
344
+ Access the current request ID for correlation:
345
+
346
+ ```ruby
347
+ client = Anthropic::Client.new
348
+
349
+ response = client.messages(
350
+ parameters: {
351
+ model: "claude-3-sonnet-20240229",
352
+ max_tokens: 1000,
353
+ messages: [{ role: "user", content: "Hello" }]
354
+ }
355
+ )
356
+
357
+ # Get the request ID that was logged to Coolhand
358
+ request_id = Thread.current[:coolhand_current_request_id]
359
+ puts "Logged to Coolhand with ID: #{request_id}"
360
+
361
+ # Use this ID for feedback or debugging
362
+ feedback_service = Coolhand::Ruby::FeedbackService.new(Coolhand.configuration)
363
+ feedback_service.create_feedback(
364
+ llm_request_log_id: request_id,
365
+ like: true,
366
+ explanation: "Great response quality"
367
+ )
368
+ ```
369
+
370
+ ## Troubleshooting
371
+
372
+ ### Debug Mode
373
+
374
+ Enable verbose logging to see what's being intercepted:
375
+
376
+ ```ruby
377
+ Coolhand.configure do |config|
378
+ config.api_key = 'your_api_key'
379
+ config.silent = false # Enable debug output
380
+ end
381
+
382
+ # Now you'll see console output like:
383
+ # "โœ… Coolhand ready - will log OpenAI and Anthropic (official gem) calls"
384
+ # "COOLHAND: โš ๏ธ Warning: Both 'anthropic' and 'ruby-anthropic' gems are installed..."
385
+ ```
386
+
387
+ ### Common Issues
388
+
389
+ #### 1. Gem Not Detected
390
+
391
+ **Problem**: Coolhand says "Anthropic gem not loaded"
392
+
393
+ **Solution**: Ensure you require the gem before configuring Coolhand:
394
+
395
+ ```ruby
396
+ require 'anthropic' # Must come before coolhand/ruby
397
+ require 'coolhand/ruby'
398
+
399
+ Coolhand.configure do |config|
400
+ config.api_key = 'your_api_key'
401
+ end
402
+ ```
403
+
404
+ #### 2. Duplicate Requests
405
+
406
+ **Problem**: Seeing requests logged twice in dashboard
407
+
408
+ **Cause**: Usually indicates both gems are installed and conflicting
409
+
410
+ **Solution**: Choose one gem and uninstall the other:
411
+
412
+ ```bash
413
+ # Keep official gem
414
+ gem uninstall ruby-anthropic
415
+
416
+ # OR keep community gem
417
+ gem uninstall anthropic
418
+ ```
419
+
420
+ #### 3. Missing Streaming Data
421
+
422
+ **Problem**: Only seeing individual chunks, not complete response
423
+
424
+ **Cause**: Custom streaming handling interfering with automatic detection
425
+
426
+ **Solution**: Let Coolhand handle streaming automatically:
427
+
428
+ ```ruby
429
+ # โŒ Don't manually collect chunks for logging
430
+ response = client.messages(parameters: { stream: true })
431
+ manual_collection = ""
432
+ response.each { |chunk| manual_collection += chunk.delta.text }
433
+
434
+ # โœ… Just process chunks normally - Coolhand handles logging
435
+ response = client.messages(parameters: { stream: true })
436
+ response.each { |chunk| print chunk.delta.text }
437
+ ```
438
+
439
+ #### 4. Performance Concerns
440
+
441
+ **Problem**: Worried about monitoring overhead
442
+
443
+ **Solution**: Monitoring is asynchronous and negligible:
444
+
445
+ ```ruby
446
+ # Monitoring happens in background threads
447
+ # Your application performance is unaffected
448
+ require 'benchmark'
449
+
450
+ time = Benchmark.measure do
451
+ 1000.times do
452
+ client.messages(
453
+ parameters: {
454
+ model: "claude-3-haiku-20240307", # Fast model for testing
455
+ max_tokens: 100,
456
+ messages: [{ role: "user", content: "Hi" }]
457
+ }
458
+ )
459
+ end
460
+ end
461
+
462
+ puts "Time with monitoring: #{time.real}s"
463
+ # Overhead is typically < 1ms per request
464
+ ```
465
+
466
+ ### Testing
467
+
468
+ #### Test Environment Setup
469
+
470
+ ```ruby
471
+ # spec/spec_helper.rb or test/test_helper.rb
472
+ if Rails.env.test?
473
+ Coolhand.configure do |config|
474
+ config.api_key = 'test_key_do_not_send_requests'
475
+ config.silent = true
476
+ end
477
+ end
478
+ ```
479
+
480
+ #### Mocking for Tests
481
+
482
+ ```ruby
483
+ # spec/support/anthropic_mock.rb
484
+ RSpec.configure do |config|
485
+ config.before(:each) do
486
+ # Mock Anthropic responses to avoid real API calls
487
+ allow_any_instance_of(Anthropic::Client).to receive(:messages).and_return(
488
+ double(
489
+ content: [double(text: "Mocked response")],
490
+ model: "claude-3-sonnet-20240229"
491
+ )
492
+ )
493
+ end
494
+ end
495
+ ```
496
+
497
+ ## Best Practices
498
+
499
+ 1. **Choose One Gem**: Avoid installing both `anthropic` and `ruby-anthropic` gems
500
+ 2. **Secure API Keys**: Use environment variables or Rails credentials, never commit keys
501
+ 3. **Silent in Production**: Set `config.silent = true` in production environments
502
+ 4. **Monitor Performance**: Use fast models (haiku) for high-frequency requests
503
+ 5. **Request Correlation**: Use thread-local request IDs for debugging and feedback
504
+ 6. **Streaming Efficiency**: Let Coolhand handle streaming accumulation automatically
505
+ 7. **Test Safely**: Mock API responses in test environments to avoid real charges
506
+
507
+ ## API Reference
508
+
509
+ For complete API documentation, see:
510
+ - [Official Anthropic Gem](https://github.com/anthropics/anthropic-sdk-ruby)
511
+ - [Community Ruby-Anthropic Gem](https://github.com/alexrudall/ruby-anthropic)
512
+ - [Coolhand Feedback API](../README.md#feedback-api)
513
+
514
+ ## Support
515
+
516
+ - **Coolhand Issues**: [GitHub Issues](https://github.com/Coolhand-Labs/coolhand-ruby/issues)
517
+ - **Anthropic API**: [Anthropic Documentation](https://docs.anthropic.com/)
518
+ - **Gem Conflicts**: Check this guide's troubleshooting section