27f196d333
Phase 2 of foreman: the daemon now acts as a transparent Ollama proxy. - internal/ollama: Client interface and HTTP implementation for chat (streaming + non-streaming), embed, tags, ps with auth forwarding, NDJSON streaming via bufio.Scanner, and connection vs HTTP error classification via custom error types. - internal/ollama: ModelInventory with background poller for /api/tags and /api/ps, degraded mode on target unreachable with model retention, automatic recovery on reconnect. - internal/server: Passthrough routes (/api/chat, /api/tags, /api/ps, /api/embed, /api/embeddings) with model validation, chat serialization gate (capacity-1 channel), concurrent embedding bypass (ADR-0013), NDJSON streaming with per-chunk flush, and degraded health reporting. - cmd/foreman: Full serve wiring with Ollama client, poller goroutine, embedder warmup (keep_alive:-1), and signal-based shutdown. The Mac is now usable as a go-llm target through foreman. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42 lines
1.3 KiB
Go
42 lines
1.3 KiB
Go
package ollama
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// ConnectionError wraps a network-level error when the Ollama target is unreachable.
|
|
// Phase 3 uses this to distinguish connection failures (retry-eligible) from HTTP
|
|
// errors (usually not retryable).
|
|
//
|
|
// Why: callers must differentiate "target is down" from "target returned 4xx/5xx"
|
|
// to decide on retry strategy.
|
|
// What: wraps a net-level error and satisfies the error and Unwrap interfaces.
|
|
// Test: create a ConnectionError, verify errors.Is/As can match it.
|
|
type ConnectionError struct {
|
|
URL string
|
|
Err error
|
|
}
|
|
|
|
func (e *ConnectionError) Error() string {
|
|
return fmt.Sprintf("connection to ollama target %s failed: %v", e.URL, e.Err)
|
|
}
|
|
|
|
func (e *ConnectionError) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// HTTPError represents a non-2xx HTTP response from the Ollama target.
|
|
//
|
|
// Why: callers need the status code to distinguish client errors (4xx) from
|
|
// server errors (5xx) and decide on retry logic.
|
|
// What: holds the HTTP status code and response body for error diagnosis.
|
|
// Test: create an HTTPError with status 500, verify Error() includes the code.
|
|
type HTTPError struct {
|
|
StatusCode int
|
|
Body string
|
|
}
|
|
|
|
func (e *HTTPError) Error() string {
|
|
return fmt.Sprintf("ollama target returned HTTP %d: %s", e.StatusCode, e.Body)
|
|
}
|