Documentation
¶
Overview ¶
Package provcore is the shared kernel under the provider WIRE adapters: the bounded retry loop, the tuned turn HTTP client, the native web-search tool swap, and the context-overflow classification — protocol plumbing shared by every adapter (the gateway's and the extracted ones alike), with NO routing policy, keys, or metering in it.
This package exists so each provider protocol is implemented exactly ONCE and reused by both the hosted gateway and the CLI's direct endpoint mode — providers/{openai,anthropic,gemini,compat,memcode} all sit on this kernel. It imports NO vendor SDK (a guard test enforces it): adapters register their SDK's error shape via RegisterErrorInfo at init. Policy stays in the CLI's Runner; money stays in the gateway; this is transport.
Index ¶
- Constants
- func APIErrorInfo(err error) (status int, header http.Header, ok bool)
- func Backoff(attempt int) time.Duration
- func IsOverflowMessage(msg string) bool
- func IsRetryable(code int) bool
- func LogToolInputMalformed(provider string, err error)
- func NewTurnHTTPClient() *http.Client
- func RegisterErrorInfo(fn ErrorInfoExtractor)
- func RetryAfter(h http.Header) time.Duration
- func SplitWebSearchTool(tools []wire.ToolDef) ([]wire.ToolDef, bool)
- func StreamWithRetry(ctx context.Context, once func() (wire.Response, bool, error)) (wire.Response, error)
- func WithRetry[T any](ctx context.Context, fn func() (T, error)) (T, error)
- type ContextOverflowError
- type ErrorInfoExtractor
Constants ¶
const WebSearchSystemPrompt = `` /* 277-byte string literal not displayed */
WebSearchSystemPrompt is the system prompt for every adapter's web-search side channel (a research assistant that cites sources) — hoisted here so the three vendors' prompts can never drift apart.
const WebSearchToolName = "web_search"
WebSearchToolName is the CLI's web_search FUNCTION tool — adapters with a native in-request search swap it for the vendor built-in.
Variables ¶
This section is empty.
Functions ¶
func APIErrorInfo ¶
APIErrorInfo extracts the HTTP status + response header from a provider SDK error via the registered extractors. ok is false for transport/non-API errors (not retryable).
func Backoff ¶
Backoff is the bounded exponential delay for one attempt: 0.5s, 1s, 2s, 4s… capped at 8s.
func IsOverflowMessage ¶
IsOverflowMessage reports whether a backend error message is a context-length rejection (input + max_tokens exceeds the served window). Covers the OpenAI-compat phrasings and Anthropic's ("prompt is too long: N tokens > M maximum"), so one classifier serves every adapter.
func IsRetryable ¶
IsRetryable reports whether an HTTP status is worth another attempt: 429 (rate limit), 529 (Anthropic overloaded), and any 5xx. 4xx (bad request/ auth) is not.
func LogToolInputMalformed ¶ added in v0.27.0
LogToolInputMalformed reports a replayed tool_use block whose Input is not valid JSON — telemetry, never fatal. The event is marshaled (never string- interpolated, which produced invalid JSON whenever the error text carried a quote) and written to stderr, never stdout, so it can't corrupt the TUI.
func NewTurnHTTPClient ¶
NewTurnHTTPClient returns the HTTP client used for provider turn calls.
Deliberately NO http.Client.Timeout: that caps the ENTIRE exchange including reading a streamed body, which decapitates exactly the turns the escalation ladder exists for (frontier xhigh-reasoning turns, 1M-context plan synthesis) at the cap with partial usage billed. Turn lifetime is bounded by the request context (client cancel, server request timeout); the transport bounds only connection setup and time-to-first-byte.
func RegisterErrorInfo ¶
func RegisterErrorInfo(fn ErrorInfoExtractor)
RegisterErrorInfo adds a vendor error extractor (called from adapter init).
func RetryAfter ¶
RetryAfter parses a Retry-After header — the seconds form or the HTTP-date form (RFC 9110 allows both) — returning 0 when absent, unparseable, or already in the past.
func SplitWebSearchTool ¶
SplitWebSearchTool returns tools without the web_search function def, plus whether it was present. Copies on removal — the caller's shared slice is never mutated.
func StreamWithRetry ¶ added in v0.27.0
func StreamWithRetry(ctx context.Context, once func() (wire.Response, bool, error)) (wire.Response, error)
StreamWithRetry is WithRetry's streaming twin — the ONE emitted-aware stream retry policy, shared by every native adapter (each previously ran its own copy of this loop with diverging attempt counts and no Retry-After). once runs a single streaming attempt and reports whether any content was forwarded to the caller's handler; a stream can't resume mid-flight, so a retry happens ONLY when nothing was emitted yet — retrying after partial output would duplicate it for the caller. Transient API failures (429/529/ 5xx via the registered extractors) retry up to 5 attempts with Backoff, honoring Retry-After when the vendor's error carries a header. The failing attempt's response is returned alongside the error so partial usage still reaches the meter.
Types ¶
type ContextOverflowError ¶
type ContextOverflowError struct {
Backend string // which lane overflowed ("anthropic" | "openai" | "fireworks" | …)
Message string
}
ContextOverflowError is a context-window overflow from ANY backend — the prompt + reserved output exceeds the served window. It is the signal the CLI watches for to compact-and-retry the turn rather than fail it.
func (*ContextOverflowError) Error ¶
func (e *ContextOverflowError) Error() string
type ErrorInfoExtractor ¶
ErrorInfoExtractor recognizes ONE vendor SDK's API error shape, returning its HTTP status + response header. Each adapter registers its own at init — this kernel imports NO vendor SDKs (registering here instead of type- asserting is what keeps provcore, and everything that touches it, from hard-linking every vendor's client library).