Skip to content

Commit 1dd796d

Browse files
authored
refactor(errors): Replace string pattern matching with SDK error types (#18)
- Add sentinel field to BaseError for single Is() method implementation - Remove 10 boilerplate Is() methods from concrete error types - Simplify constructors by removing redundant message parameter - Delete fragile string pattern matching (Convert(), ConvertWithRegex()) - Add provider-specific ConvertError() methods using SDK error types - Add ErrorConverter interface for consistent error handling across providers - Add error code constants (CodeRateLimit, CodeAuthError, etc.) - Add comprehensive table-driven tests for error conversion
1 parent d078506 commit 1dd796d

File tree

8 files changed

+765
-298
lines changed

8 files changed

+765
-298
lines changed

CONTRIBUTING.md

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,9 @@ type Provider struct {
132132

133133
// Ensure interface compliance.
134134
var (
135-
_ providers.Provider = (*Provider)(nil)
136135
_ providers.CapabilityProvider = (*Provider)(nil)
136+
_ providers.ErrorConverter = (*Provider)(nil)
137+
_ providers.Provider = (*Provider)(nil)
137138
)
138139

139140
func New(opts ...config.Option) (*Provider, error) {
@@ -169,14 +170,42 @@ func (p *Provider) Capabilities() providers.Capabilities {
169170
}
170171

171172
func (p *Provider) Completion(ctx context.Context, params providers.CompletionParams) (*providers.ChatCompletion, error) {
172-
// Convert params to provider format.
173-
// Make API call.
174-
// Convert response to providers format.
175-
// Handle errors with errors.Convert().
173+
req := convertParams(params)
174+
175+
resp, err := p.client.Messages.New(ctx, req)
176+
if err != nil {
177+
return nil, p.ConvertError(err)
178+
}
179+
180+
return convertResponse(resp), nil
176181
}
177182

178183
func (p *Provider) CompletionStream(ctx context.Context, params providers.CompletionParams) (<-chan providers.ChatCompletionChunk, <-chan error) {
179-
// Implement streaming.
184+
// Implement streaming, use p.ConvertError() for errors.
185+
}
186+
187+
// ConvertError converts SDK errors to unified error types.
188+
// Implements providers.ErrorConverter.
189+
func (p *Provider) ConvertError(err error) error {
190+
if err == nil {
191+
return nil
192+
}
193+
194+
var apiErr *sdk.Error
195+
if !stderrors.As(err, &apiErr) {
196+
return errors.NewProviderError(providerName, err)
197+
}
198+
199+
switch apiErr.StatusCode {
200+
case 401:
201+
return errors.NewAuthenticationError(providerName, err)
202+
case 429:
203+
return errors.NewRateLimitError(providerName, err)
204+
case 404:
205+
return errors.NewModelNotFoundError(providerName, err)
206+
default:
207+
return errors.NewProviderError(providerName, err)
208+
}
180209
}
181210
```
182211

@@ -234,7 +263,7 @@ func TestIntegrationCompletion(t *testing.T) {
234263
- [ ] Implements `Provider` interface
235264
- [ ] Implements `CapabilityProvider` interface
236265
- [ ] Normalizes responses to OpenAI format
237-
- [ ] Normalizes errors using `errors.Convert()`
266+
- [ ] Implements `ErrorConverter` interface with `ConvertError()` method
238267
- [ ] Has unit tests with >80% coverage
239268
- [ ] Has integration tests (skipped when no API key)
240269
- [ ] Passes `golangci-lint`

0 commit comments

Comments
 (0)