- L1: gofmt fix on models.go:81 - L2: rewrite misleading RunFailure doc comment (didn't actually embed APIError) - L3: tighten Client doc to warn against post-construction field mutation - L4: errors.New for non-formatting Errorf calls - L5: add TestUploadFile lifting coverage from 0% → 100% on UploadFile - L7: add context cancellation mid-multipart test Audit: memory/clawdforge-audits/go-3c62613.md
61 lines
1.9 KiB
Go
61 lines
1.9 KiB
Go
package clawdforge
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// ErrAuth is the sentinel returned for 401/403 responses from clawdforge.
|
|
// Use errors.Is(err, ErrAuth) to detect auth failures.
|
|
var ErrAuth = errors.New("clawdforge: authentication failed")
|
|
|
|
// APIError carries a non-2xx response from clawdforge — status code plus
|
|
// the response body (truncated to a sane size). It is returned for any
|
|
// HTTP status >= 400 that isn't an auth failure.
|
|
type APIError struct {
|
|
StatusCode int
|
|
// Body is the raw response body (truncated). Useful for debugging.
|
|
Body string
|
|
// Message is a short human-readable summary derived from the body
|
|
// when the body is JSON of the form {"error": "..."} or {"detail": "..."}.
|
|
Message string
|
|
}
|
|
|
|
func (e *APIError) Error() string {
|
|
if e.Message != "" {
|
|
return fmt.Sprintf("clawdforge: HTTP %d: %s", e.StatusCode, e.Message)
|
|
}
|
|
return fmt.Sprintf("clawdforge: HTTP %d: %s", e.StatusCode, e.Body)
|
|
}
|
|
|
|
// TransportError wraps a low-level network/transport failure (DNS, connect
|
|
// refused, TLS, EOF, context cancellation, etc.). The wrapped error is
|
|
// available via errors.Unwrap.
|
|
type TransportError struct {
|
|
Op string
|
|
Err error
|
|
}
|
|
|
|
func (e *TransportError) Error() string {
|
|
return fmt.Sprintf("clawdforge: transport %s: %v", e.Op, e.Err)
|
|
}
|
|
|
|
func (e *TransportError) Unwrap() error { return e.Err }
|
|
|
|
// RunFailure represents a 502 response from /run — clawdforge accepted the
|
|
// request but `claude -p` failed (timeout, non-zero exit, etc.). The body
|
|
// fields mirror the server's failure shape.
|
|
//
|
|
// RunFailure has its own StatusCode field (always 502) and is distinct from
|
|
// APIError so callers can branch on errors.As(err, &rf).
|
|
type RunFailure struct {
|
|
StatusCode int
|
|
Err string `json:"error"`
|
|
Stderr string `json:"stderr"`
|
|
DurationMS int `json:"duration_ms"`
|
|
StopReason string `json:"stop_reason"`
|
|
}
|
|
|
|
func (e *RunFailure) Error() string {
|
|
return fmt.Sprintf("clawdforge: run failed (stop_reason=%s): %s", e.StopReason, e.Err)
|
|
}
|