Preserve LLM generation failure metadata
This commit is contained in:
@@ -13,16 +13,42 @@ var ErrLLMCapacityExceeded = errors.New("LLM capacity exceeded")
|
||||
// ErrLLMGeneration identifies a provider generation failure.
|
||||
var ErrLLMGeneration = errors.New("LLM generation failed")
|
||||
|
||||
type LLMGenerationFailureKind string
|
||||
|
||||
const (
|
||||
LLMGenerationFailureGeneration LLMGenerationFailureKind = "generation"
|
||||
LLMGenerationFailureTransport LLMGenerationFailureKind = "transport"
|
||||
LLMGenerationFailureProviderStatus LLMGenerationFailureKind = "provider_status"
|
||||
LLMGenerationFailureMalformedResponse LLMGenerationFailureKind = "malformed_response"
|
||||
)
|
||||
|
||||
type LLMGenerationMetadata struct {
|
||||
FailureKind LLMGenerationFailureKind
|
||||
RetriesExhausted bool
|
||||
Attempts uint64
|
||||
}
|
||||
|
||||
type LLMGenerationError struct {
|
||||
status int
|
||||
diagnostic string
|
||||
status int
|
||||
diagnostic string
|
||||
failureKind LLMGenerationFailureKind
|
||||
exhausted bool
|
||||
attempts uint64
|
||||
}
|
||||
|
||||
func NewLLMGenerationError(status int, diagnostic string) *LLMGenerationError {
|
||||
return NewLLMGenerationErrorWithMetadata(status, diagnostic, LLMGenerationMetadata{})
|
||||
}
|
||||
|
||||
func NewLLMGenerationErrorWithMetadata(status int, diagnostic string, metadata LLMGenerationMetadata) *LLMGenerationError {
|
||||
if status < 0 {
|
||||
status = 0
|
||||
}
|
||||
return &LLMGenerationError{status: status, diagnostic: diagnostic}
|
||||
kind := metadata.FailureKind
|
||||
if kind == "" {
|
||||
kind = LLMGenerationFailureGeneration
|
||||
}
|
||||
return &LLMGenerationError{status: status, diagnostic: diagnostic, failureKind: kind, exhausted: metadata.RetriesExhausted, attempts: metadata.Attempts}
|
||||
}
|
||||
func (e *LLMGenerationError) Error() string {
|
||||
if e == nil || e.diagnostic == "" {
|
||||
@@ -37,3 +63,21 @@ func (e *LLMGenerationError) StatusCode() int {
|
||||
}
|
||||
return e.status
|
||||
}
|
||||
|
||||
func (e *LLMGenerationError) FailureKind() LLMGenerationFailureKind {
|
||||
if e == nil || e.failureKind == "" {
|
||||
return LLMGenerationFailureGeneration
|
||||
}
|
||||
return e.failureKind
|
||||
}
|
||||
|
||||
func (e *LLMGenerationError) RetriesExhausted() bool {
|
||||
return e != nil && e.exhausted
|
||||
}
|
||||
|
||||
func (e *LLMGenerationError) Attempts() uint64 {
|
||||
if e == nil {
|
||||
return 0
|
||||
}
|
||||
return e.attempts
|
||||
}
|
||||
|
||||
22
internal/framework/contracts/errors_test.go
Normal file
22
internal/framework/contracts/errors_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package contracts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLLMGenerationErrorPreservesApplicationMetadata(t *testing.T) {
|
||||
legacy := NewLLMGenerationError(503, "provider failure")
|
||||
if !errors.Is(legacy, ErrLLMGeneration) || legacy.StatusCode() != 503 || legacy.FailureKind() != LLMGenerationFailureGeneration || legacy.RetriesExhausted() || legacy.Attempts() != 0 {
|
||||
t.Fatalf("legacy generation error = %#v", legacy)
|
||||
}
|
||||
|
||||
err := NewLLMGenerationErrorWithMetadata(429, "provider failure", LLMGenerationMetadata{
|
||||
FailureKind: LLMGenerationFailureProviderStatus,
|
||||
RetriesExhausted: true,
|
||||
Attempts: 3,
|
||||
})
|
||||
if !errors.Is(err, ErrLLMGeneration) || err.StatusCode() != 429 || err.FailureKind() != LLMGenerationFailureProviderStatus || !err.RetriesExhausted() || err.Attempts() != 3 {
|
||||
t.Fatalf("generation error = %#v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user