Files
majordomo/provider/llamaswap/health.go
T
steve 9c0ac1d60b
CI / Tidy (pull_request) Successful in 10m2s
CI / Build & Test (pull_request) Successful in 10m24s
fix: address gadfly review — filename sanitization, truncation guard, shared plumbing
- Transcribe: sanitize the caller-supplied multipart filename (CR/LF
  would inject Content-Disposition headers; upload metadata is
  untrusted), always send the required model/response_format fields,
  parse MIME parameters before extension matching, and give audio/opus
  its own .opus extension.
- doRaw: a response larger than maxResponseBytes is now an error, not a
  silent truncation.
- Shared plumbing: requireBaseURL() + newRequest() helpers replace the
  7x-duplicated guard/error string and the triplicated request
  building across doJSON/doRaw/Health.
- Health: non-2xx now returns *llm.APIError (package convention,
  programmatically distinguishable from transport failure) instead of
  a one-off unexported error type.
- Speak: reject negative Speed; speechMIME no longer accepts video/*
  Content-Types.
- image.go: Generate/Edit share one sdWire validate+map helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXQxVhXBw8PwFAtsVrXSmj
2026-07-11 23:46:23 -04:00

45 lines
1.3 KiB
Go

package llamaswap
import (
"context"
"fmt"
"io"
"net/http"
"gitea.stevedudenhoeffer.com/steve/majordomo/llm"
)
// Health reports whether the llama-swap instance is reachable (GET
// {base}/health, which answers "OK" without touching any model). A nil error
// means the proxy itself is up — it says nothing about how long a subsequent
// request will take (a cold model swap can still block for minutes). Bound
// the probe with a short context deadline; the client has no timeout by
// design.
//
// Failure taxonomy matches the rest of the package: transport failures wrap
// the raw net error; a reachable-but-unhealthy status comes back as
// *llm.APIError, so callers can errors.As-distinguish the two.
func (p *Provider) Health(ctx context.Context) error {
if err := p.requireBaseURL(); err != nil {
return err
}
req, err := p.newRequest(ctx, http.MethodGet, "/health", "", nil)
if err != nil {
return err
}
resp, err := p.client.Do(req)
if err != nil {
return fmt.Errorf("llama-swap: health probe: %w", err)
}
defer resp.Body.Close()
_, _ = io.Copy(io.Discard, io.LimitReader(resp.Body, 1<<10))
if resp.StatusCode/100 != 2 {
return &llm.APIError{
Provider: p.name,
Status: resp.StatusCode,
Message: "health endpoint returned a non-2xx status",
}
}
return nil
}