provcore

package
v0.27.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 11 Imported by: 0

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

View Source
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.

View Source
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

func APIErrorInfo(err error) (status int, header http.Header, ok bool)

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

func Backoff(attempt int) time.Duration

Backoff is the bounded exponential delay for one attempt: 0.5s, 1s, 2s, 4s… capped at 8s.

func IsOverflowMessage

func IsOverflowMessage(msg string) bool

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

func IsRetryable(code int) bool

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

func LogToolInputMalformed(provider string, err error)

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

func NewTurnHTTPClient() *http.Client

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

func RetryAfter(h http.Header) time.Duration

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

func SplitWebSearchTool(tools []wire.ToolDef) ([]wire.ToolDef, bool)

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.

func WithRetry

func WithRetry[T any](ctx context.Context, fn func() (T, error)) (T, error)

WithRetry wraps an SDK call with bounded exponential backoff: up to 5 attempts, 0.5→8s delays (doubling each attempt), Retry-After honored, 429 + 529 + 5xx retried. The SDK's own retry is disabled by the adapters (WithMaxRetries(0)) so this loop is the only one.

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

type ErrorInfoExtractor func(error) (status int, header http.Header, ok bool)

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).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL