providertest

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package providertest is the shared contract suite every provider.Provider adapter must pass (CLAUDE.md: backend variability lives behind an interface with one shared suite, as internal/sandbox/sandboxtest and internal/blob/ blobtest already do for their backends). It asserts the protocol-agnostic invariants of the Provider/Stream contract — what every adapter owes its caller, whether the turn was carried over Anthropic Messages or OpenAI Chat Completions: a stream terminates with exactly one done chunk carrying a stop reason; a well-formed tool turn's done chunk carries stop_reason tool_use — which the OpenAI adapter forces from the tool calls it saw while the Anthropic adapter passes the endpoint's label straight through, so what this pins is the two adapters agreeing on a well-formed turn, NOT a promise about either endpoint behind them: the brain classifies a turn on its tool blocks rather than its label (#181); a tool call's input accumulates and defaults to {} when empty; a usage reading is nil only when the endpoint reported none (not when it reported zeroes, #90); a cancelled context surfaces as a stream error rather than a silent completion; an endpoint that goes silent — before its response headers or in the middle of its stream — ends the turn within the configured stall budget, while one that sends nothing but keepalives is left to think (#121); and Close releases the stream both after a completed turn and before draining one.

Protocol-specific behavior stays in each adapter's own package: the wire request shape, credential redaction, the OpenAI lossy conversions, and the finish_reason -> stop_reason mapping table are NOT here.

It is test support; production code must never import it. A backend supplies a Backend that renders the suite's abstract Script into its own streaming wire protocol on a fake upstream — the providertest analogue of sandboxtest.Harness / blobtest's newStore.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(t *testing.T, b Backend)

Run exercises the provider.Provider contract against one backend.

Types

type Backend

type Backend struct {
	// Turn stages a fake upstream that plays s to completion — streaming its
	// text and tool call, reporting its usage (or none when Script.Usage is
	// nil), and closing the turn the way this protocol naturally ends one — and
	// returns a provider wired to it. A non-empty Tool.Input MUST be streamed
	// across at least two wire frames so the suite exercises input
	// accumulation rather than a single-frame input.
	Turn func(t *testing.T, s Script) provider.Provider

	// Hang stages an upstream that streams exactly enough to yield one text
	// chunk and then blocks without completing the turn, so the suite can
	// cancel the request context mid-stream — or let the provider's own stall
	// budget end it. It returns a provider wired to it, configured with stall as
	// its Config.StallTimeout (zero for the default).
	Hang func(t *testing.T, stall time.Duration) provider.Provider

	// Wedge stages an upstream that accepts the connection and then answers
	// nothing at all — no response headers, ever — the wedged proxy of #121. It
	// returns a provider wired to it with stall as its Config.StallTimeout.
	Wedge func(t *testing.T, stall time.Duration) provider.Provider

	// Keepalive stages an upstream that sends nothing but this protocol's
	// content-free liveness frames (an Anthropic ping, an SSE comment) every
	// stall/8 for 3*stall, and only then completes a one-word turn. It returns a
	// provider wired to it with stall as its Config.StallTimeout, so the suite
	// can hold an adapter to the other half of the stall contract: a quiet but
	// living endpoint must not be killed. The frames are eight to a budget so
	// that a loaded machine has to lose seven in a row before this reads as a
	// stall — the margin is the difference between a contract test and a flake.
	Keepalive func(t *testing.T, stall time.Duration) provider.Provider
}

Backend renders Scripts into running providers for one protocol.

type Script

type Script struct {
	Text  string             // assistant text streamed before any tool call
	Tool  *ToolCall          // an optional tool call the turn makes
	Usage *domain.ModelUsage // usage the upstream reports, or nil for "reported none"
}

Script is an abstract model turn the suite asks a backend to stage. A backend renders it into its own streaming wire protocol; only the fields a given subtest sets are meaningful.

type ToolCall

type ToolCall struct {
	ID   string
	Name string
	// Input is a compact JSON object the accumulated tool input must equal,
	// e.g. `{"command":"ls"}` or `{}` for an argument-less call.
	Input string
}

ToolCall is the single tool call a Script's turn makes.

Jump to

Keyboard shortcuts

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