67 lines
2.5 KiB
Go
67 lines
2.5 KiB
Go
package knowledge
|
|
|
|
import "fmt"
|
|
|
|
// Structured errors, per §10: a code, never a bare string, and user-facing text
|
|
// derived at the surface rather than raised from here.
|
|
//
|
|
// The codes matter more than they look. "the embedding provider is down" and
|
|
// "this deployment has no embedding credential" are the same sentence to a
|
|
// user and completely different to an operator — one is a page, the other is a
|
|
// configuration task nobody has done. Flattening them into a single failure
|
|
// makes that distinction unanswerable from a log.
|
|
type Error struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
Cause error `json:"-"`
|
|
}
|
|
|
|
func (e *Error) Error() string {
|
|
if e.Cause != nil {
|
|
return fmt.Sprintf("%s: %s: %v", e.Code, e.Message, e.Cause)
|
|
}
|
|
return fmt.Sprintf("%s: %s", e.Code, e.Message)
|
|
}
|
|
|
|
func (e *Error) Unwrap() error { return e.Cause }
|
|
|
|
const (
|
|
// ErrNoPrincipal is retrieval called without a caller. §5: there is no
|
|
// overload without a principal, and this is what enforces it at run time
|
|
// for a caller that assembled the struct by hand.
|
|
ErrNoPrincipal = "knowledge.no_principal"
|
|
|
|
// ErrNoSources is retrieval called without naming a corpus. An agent reads
|
|
// the sources its spec declares; an empty list is not "all of them".
|
|
ErrNoSources = "knowledge.no_sources"
|
|
|
|
// ErrNoAudience is an ingest whose document reaches nobody. §5.
|
|
ErrNoAudience = "knowledge.no_audience"
|
|
|
|
// ErrNotConfigured is a missing embedding credential, or the stand-in
|
|
// embedder refusing to run in production.
|
|
ErrNotConfigured = "knowledge.not_configured"
|
|
|
|
// ErrEmbedUnavailable is a provider that is reachable-in-principle and
|
|
// failing now: a timeout, a 429, a 503. Retryable.
|
|
ErrEmbedUnavailable = "knowledge.embed_unavailable"
|
|
|
|
// ErrEmbedFailed is a provider answering something this code cannot use.
|
|
// Not retryable — the same request will fail the same way.
|
|
ErrEmbedFailed = "knowledge.embed_failed"
|
|
|
|
// ErrModelMismatch is a corpus embedded with one model being searched with
|
|
// another. Refused rather than served: vectors from two models are not
|
|
// comparable, and the failure mode is confident nonsense.
|
|
ErrModelMismatch = "knowledge.model_mismatch"
|
|
|
|
// ErrIngestFailed and ErrRetrieveFailed are the database saying no.
|
|
ErrIngestFailed = "knowledge.ingest_failed"
|
|
ErrRetrieveFailed = "knowledge.retrieve_failed"
|
|
)
|
|
|
|
// Retryable reports whether the same call might succeed later.
|
|
func (e *Error) Retryable() bool {
|
|
return e.Code == ErrEmbedUnavailable
|
|
}
|