Help us shape the future of Go! Take the 2026 Go Developer Survey

inference

package module
v0.15.0 Latest Latest
Warning

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

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

README

inference

github.com/looprig/inference is Looprig's provider-neutral inference seam. It defines the Client / Request / Response contract over Core's content transcript types. It also has one wire codec per model API format, each translating between the neutral transcript and that format's published contract, and a generic HTTP transport that combines a codec, a router and an authorizer into a Client.

The module is provider-policy-free. It holds no provider default endpoints, no model catalogue and no credential discovery. Those live in llm.

Status

Released. Implemented API formats (model.APIFormat):

Format Codec package
openai (Chat Completions) codec/openaiapi
openai-responses codec/openairesponses
anthropic (Messages) codec/anthropicapi
gemini (generateContent) codec/geminiapi
bedrock-converse codec/bedrockconverse

Also implemented:

  • Request and stream encoding and decoding, with SSE, NDJSON and AWS Event Stream framing.
  • Structured output (Request.Output, DecodeOutput) and tool choice.
  • Normalized token usage and deterministic context counting.
  • Bounded, classified retry through retry.
  • The loopback gateway, which lets a client speaking one dialect reach any injected inference.Client target. See docs/inference-gateway.md.

Each codec's encoded request bodies are checked in tests against the format's official request schema. The schemas are in codec/conformance and are regenerated with make conformance-schemas.

Install

go get github.com/looprig/inference@latest

Packages

Package Purpose
inference Client, Request, Response, tools, tool choice, structured output, ValidateRequestFeatures.
model Model identity, API format, capabilities, context limits, sampling and effort (model.CustomModel).
codec Codec interfaces: client-side request encoders, response and stream decoders, server-side ServerCodec.
codec/openaiapi, codec/openairesponses, codec/anthropicapi, codec/geminiapi, codec/bedrockconverse One wire codec per API format.
codec/conformance Schema conformance gate for provider wire fixtures and encoded requests. cmd/schemagen regenerates its schemas.
codec/servertest Reusable contract suite for codec.ServerCodec implementations.
transport Connection-bound HTTP Client built from an Endpoint, a route.Router, a codec.Codec and an authorizer.
route Routers for the bundled wire shapes (StaticChat, GeminiGenerateContent).
stream Pull-based StreamReader, stream frames, finish reasons and stream results.
retry inference.Client decorator with bounded, classified retry and exponential backoff.
gateway Loopback HTTP compatibility layer (Anthropic Messages, OpenAI Responses, OpenAI Chat, Gemini ingress).
contextcount Deterministic complete-request context counting.
usage Normalized token usage.
failure Provider-neutral API, network and binding failures.
inferencetest Scripted in-memory Client and Model() for keyless runs and tests.
auth Legacy authorization facade over credentials/httpauth, kept for static API keys and auth.None().
wire/sse, wire/ndjson, wire/eventstream, wire/jsonbody Byte-level framing helpers with no LLM semantics.

Usage

Build a request and compose an HTTP client for an OpenAI-compatible endpoint:

m := model.CustomModel("local", model.APIFormatOpenAI, "http://127.0.0.1:8080/v1", "demo-model")

client := transport.New(
	transport.Endpoint{BaseURL: m.BaseURL, Provider: m.Provider, APIFormat: m.APIFormat},
	route.StaticChat("/chat/completions"),
	openaiapi.Codec{},
	auth.None(), // or a credentials/httpauth Authorizer
)

resp, err := client.Invoke(ctx, inference.Request{
	Model:  m,
	System: "Answer briefly.",
	Messages: content.AgenticMessages{&content.UserMessage{Message: content.Message{
		Role:   content.RoleUser,
		Blocks: []content.Block{&content.TextBlock{Text: "Say hello."}},
	}}},
})

To use a hosted provider with its endpoint, auth policy and model catalogue already configured, take the provider package from llm. Runnable programs are in examples/: invoke, stream, retry and gateway.

Running without a provider: inferencetest

inferencetest.New returns a scripted inference.Client that needs no API key or network. Each call, through Invoke or Stream, consumes the next step of its script, and inferencetest.Model() is a descriptor that validates and declares tool and structured-output support:

client := inferencetest.New(
	inferencetest.Text("Let me check.").ToolCall("read_file", `{"path":"go.mod"}`),
	inferencetest.Text("It is module example.com/demo."),
)
def, err := loop.Define(
	loop.WithName("assistant"),
	loop.WithInference(client, inferencetest.Model()),
	// tools, access gate, ...
)
// After the turn: client.Requests() is what the model saw; client.Err()
// reports an exhausted script or a failed Step.Expect check.

A step can carry reasoning (Thinking), text, tool calls with deterministic ids (call_<call>_<n>), a finish reason and usage. It can also fail before output (Fail), fail mid-stream (StreamError), stream at a visible pace (ChunkDelay), or check its request (Expect). Echo().Repeat() answers anything with the user's last message, which suits a keyless demo. Stream emits the chunk shapes a real codec produces, and folding it yields the message Invoke returns. Like a real client, each call validates the request first.

Calls with no execution ceiling

transport.Client bounds Invoke by a whole-request timeout (5 minutes by default, WithInvokeTimeout) and Stream by a 60-second wait for response headers. For a call that may legitimately run longer, such as a slow local model or a long reasoning turn, mark its context:

ctx = transport.WithoutExecutionTimeout(ctx)
resp, err := client.Invoke(ctx, req) // or client.Stream(ctx, req)

A marked call has neither ceiling. Everything else is unchanged:

  • TLS roots and a WithRoundTripper transport;
  • dial and TLS-handshake limits;
  • redirect refusal and authorization;
  • response-size limits.

Unmarked calls are unaffected, and nothing is sent on the wire. Cancellation becomes the caller's job: the context's own cancel or deadline is the only end, and a half-open connection is detected only by TCP keepalive. llm providers built on transport.Client honour the marker as they are. llm's gemini and bedrock providers use their own HTTP client and do not.

Consumer obligation: Request.SessionID

Request.SessionID is an optional, stable identifier for a conversation. Providers that document a per-conversation header can use it. "" means absent, and no neutral codec encodes it.

ValidateRequestFeatures, which every codec runs, checks the id for every provider and refuses one that could not be sent unchanged as an HTTP header value. The reasons are control bytes, surrounding whitespace, or more than MaxSessionIDBytes (256) bytes. The error is *InvalidSessionIDError.

A refusal fails the whole request, not just the header. If you wire a session id, pre-check it with inference.ValidateRequestFeatures(inference.Request{SessionID: id}), then omit or map a refused id rather than failing every turn.

Where it sits

Tier 2 in the Looprig workspace. Direct Looprig dependencies: core, credentials, secrets. Consumers include llm, harness, eval, classifiers, mcp, tui and pluto.

Development

The Go baseline is 1.26.8. The module does not vendor. Verify it standalone:

GOWORK=off go test ./...
make check                # gofmt check, vet, staticcheck, gosec, govulncheck, race tests, build
make conformance-schemas  # re-derive codec/conformance/schema from upstream specs (network)

Other targets: fmt, fmt-check, vet, test, lint, vuln, secure, check-staticcheck, check-gosec, check-vuln, build. make fuzz only prints how to run a fuzz target:

go test -fuzz=FuzzXxx ./path/to/pkg -fuzztime=30s

The lint and security tools are pinned by tool directives in go.mod. The tests need no network, credentials or build tags.

License

Apache License 2.0. See LICENSE.

Documentation

Index

Constants

View Source
const (
	StructuredOutputToolName = "_looprig_final_output"
	StructuredOutputRevision = "structured-output/v1"
)
View Source
const (
	// MaxStructuredOutputDiagnosticBytes bounds caller-controlled string
	// metadata retained by structured-output errors.
	MaxStructuredOutputDiagnosticBytes = 128

	// MaxStructuredResultBytes bounds a native structured result before JSON
	// parsing or compaction. It matches the 1 MiB request-schema bound so both
	// structured-output boundaries have a single conservative memory ceiling.
	MaxStructuredResultBytes = 1 << 20

	// StructuredOutputFinishReasonOther classifies a non-empty finish reason
	// outside the provider-neutral set without retaining provider input.
	StructuredOutputFinishReasonOther stream.FinishReason = "other"
)
View Source
const MaxSessionIDBytes = 256

MaxSessionIDBytes is the largest permitted byte length of Request.SessionID. It keeps the header a provider receives far below the request-header limits HTTP servers enforce (an oversized header draws an opaque 431 or a dropped connection rather than a diagnosable refusal).

It equals Core's sessionwire MaxIDBytes, but that is a LENGTH bound only: it does not make every Core id a valid SessionID. Core accepts any UTF-8 id, including control characters and leading or trailing spaces, and such an id would make the request fail here. A caller wiring a Core session id into SessionID must pre-check it (with ValidateRequestFeatures on a request carrying only the id) and omit it, or map it to a sendable form, rather than fail the turn.

Variables

View Source
var (
	ToolChoiceAuto     = ToolAuto()
	ToolChoiceRequired = ToolRequired()
)

ToolChoiceAuto and ToolChoiceRequired preserve the values exposed by the original two-state ToolChoice API. New code may use ToolAuto and ToolRequired; both spellings are equal and may be compared directly.

Functions

func DecodeMessageOutput

func DecodeMessageOutput(msg *content.AIMessage, out any) error

DecodeMessageOutput extracts and strictly decodes a message into a non-nil concrete pointer. Required and other domain invariants remain caller-owned.

func DecodeOutput

func DecodeOutput(resp *Response, out any) error

DecodeOutput extracts and strictly decodes a response into a non-nil concrete pointer. Required and other domain invariants remain the caller's concern.

func StructuredMessageResult

func StructuredMessageResult(msg *content.AIMessage) (json.RawMessage, error)

StructuredMessageResult extracts exactly one JSON-object representation from assistant text fragments or one reserved terminal-tool input. Thinking blocks are ignored. The returned bytes are compacted and independently owned.

func StructuredResult

func StructuredResult(resp *Response) (json.RawMessage, error)

StructuredResult extracts one structured JSON object from a complete response and verifies that the finish reason agrees with its representation.

func ValidateOutputSchema

func ValidateOutputSchema(output OutputSchema) error

ValidateOutputSchema validates output against the bounded portable JSON Schema subset shared by provider codecs.

func ValidateRequestFeatures

func ValidateRequestFeatures(req Request) error

ValidateRequestFeatures validates provider-neutral request feature combinations before a codec attempts to encode them.

Types

type Client

type Client interface {
	Invoke(ctx context.Context, req Request) (*Response, error)
	Stream(ctx context.Context, req Request) (*stream.StreamReader[content.Chunk], error)
}

Client is the provider-neutral inference interface.

type ImageInputUnsupportedError

type ImageInputUnsupportedError struct {
	Model string
}

ImageInputUnsupportedError reports that a request thread carries image blocks but the model does not advertise the AcceptsImages capability. Model is bounded diagnostic metadata only.

func (*ImageInputUnsupportedError) Error

type InvalidSessionIDError added in v0.13.0

type InvalidSessionIDError struct {
	// Reason classifies the refusal.
	Reason SessionIDProblem
	// Index is the byte offset of the first offending byte. For
	// SessionIDTooLong it is MaxSessionIDBytes, the offset of the first byte
	// past the limit.
	Index int
}

InvalidSessionIDError reports a Request.SessionID that could not arrive at a provider byte-identical as an HTTP header field value. A provider that carries the session identity in a request header (see Request.SessionID) must send it verbatim, and an identity that is altered or refused in transit is worse than one refused locally: net/http's Transport refuses a control byte with an untyped error naming only the header, a transport that writes through Request.Write rewrites CR and LF into spaces, and surrounding whitespace is trimmed by Go's HTTP/1.1 client when it writes the header and by the recipient when it parses it. A silently-altered affinity key is undiagnosable from the provider side, where it looks like a conversation that keeps changing sessions.

The message deliberately does not echo the offending value: it is caller data and may contain arbitrary bytes. Reason and Index locate the problem instead.

func (*InvalidSessionIDError) Error added in v0.13.0

func (e *InvalidSessionIDError) Error() string

type InvalidTransientMessagesError

type InvalidTransientMessagesError struct {
	Transient int
	Messages  int
}

InvalidTransientMessagesError reports a transient-message count that falls outside the request's message slice.

func (*InvalidTransientMessagesError) Error

type MalformedStructuredOutputError

type MalformedStructuredOutputError struct {
	ReasonCode MalformedStructuredOutputReason
	Length     int
	SHA256     [sha256.Size]byte
}

MalformedStructuredOutputError reports bounded metadata about malformed model output. SHA256 and Length support correlation without retaining or exposing the raw output bytes.

func (*MalformedStructuredOutputError) Error

type MalformedStructuredOutputReason

type MalformedStructuredOutputReason string

MalformedStructuredOutputReason is a bounded classification for an invalid structured response representation. It never contains model output.

const (
	MalformedReasonNilResponse           MalformedStructuredOutputReason = "nil response"
	MalformedReasonNilMessage            MalformedStructuredOutputReason = "nil message"
	MalformedReasonWrongRole             MalformedStructuredOutputReason = "wrong role"
	MalformedReasonEmpty                 MalformedStructuredOutputReason = "empty"
	MalformedReasonMalformedJSON         MalformedStructuredOutputReason = "malformed JSON"
	MalformedReasonRootNotObject         MalformedStructuredOutputReason = "root is not object"
	MalformedReasonInvalidRepresentation MalformedStructuredOutputReason = "invalid representation"
	MalformedReasonAmbiguous             MalformedStructuredOutputReason = "ambiguous"
	MalformedReasonInvalidBlock          MalformedStructuredOutputReason = "invalid block"
	MalformedReasonNilBlock              MalformedStructuredOutputReason = "nil block"
	MalformedReasonTooLarge              MalformedStructuredOutputReason = "too large"
)

type OutputSchema

type OutputSchema struct {
	Name        string
	Description string
	Schema      json.RawMessage
	Strict      bool
}

OutputSchema is a provider-neutral request for one schema-constrained JSON object. Description must be valid UTF-8 and is limited to 4096 bytes. Schema must satisfy the portable subset checked by ValidateOutputSchema.

func (OutputSchema) Clone

func (o OutputSchema) Clone() OutputSchema

Clone returns an independent copy of the output schema.

type Request

type Request struct {
	Model             model.Model
	System            string
	Messages          content.AgenticMessages
	TransientMessages int
	Tools             []Tool
	Output            *OutputSchema
	ToolChoice        ToolChoice
	Override          *model.Sampling
	// SessionID is the OPTIONAL stable identity of the conversation these
	// messages belong to. Zero means "no conversation identity known", which is
	// what every caller that predates this field sends, so no existing request
	// changed.
	//
	// It exists because some providers offer per-conversation optimizations
	// (prompt-cache affinity, routing, cost attribution) and can only apply them
	// when every request of one conversation carries the same identifier. The
	// message thread cannot serve that purpose: context compaction rewrites it
	// mid-conversation, so a thread-derived identity silently rotates at exactly
	// the moment the cached prefix is rebuilt.
	//
	// It is provider-neutral and consumed only by providers that document such a
	// header; every other provider ignores it and its wire bytes are unchanged.
	// It is validated for every provider all the same (ValidateRequestFeatures,
	// which every codec runs before encoding), so a request that is valid for one
	// provider stays valid when a conversation switches to another. A provider
	// that forwards it sends it verbatim, so a value that could not arrive
	// upstream byte-identical as an HTTP header field value — control bytes,
	// surrounding whitespace, more than MaxSessionIDBytes bytes — is refused
	// locally with *InvalidSessionIDError rather than altered or refused in
	// transit.
	//
	// It is an identifier, not a secret, but it is caller data: this module
	// never logs it and never echoes it in an error.
	SessionID string
}

Request is the provider-neutral inference request. It carries a secret-free Model descriptor for this turn, the per-agent System prompt, the message thread, the count of trailing transient messages, the exposed tools, an optional structured Output contract, the ToolChoice (zero value: auto), and an optional per-call sampling Override (nil means use Model.Sampling).

type Response

type Response struct {
	Message      *content.AIMessage
	Usage        *content.Usage
	Model        string
	FinishReason stream.FinishReason
	// Attempts is how many attempts produced this response when served
	// through a retrying decorator; 0 means the serving client does not
	// count attempts, 1 means first-try success.
	Attempts int
}

Response is the complete provider-neutral response.

type SchemaValidationError

type SchemaValidationError struct {
	Field      SchemaValidationField
	ReasonCode SchemaValidationReason
}

SchemaValidationError reports a stable, bounded validation classification. It never retains schema bytes, property names, descriptions, or JSON decoder errors because those values may contain sensitive caller input.

func (*SchemaValidationError) Error

func (e *SchemaValidationError) Error() string

type SchemaValidationField

type SchemaValidationField string

SchemaValidationField identifies the output-schema component that failed validation. Values are stable classifications suitable for errors.As callers.

const (
	SchemaFieldName                 SchemaValidationField = "Name"
	SchemaFieldDescription          SchemaValidationField = "Description"
	SchemaFieldSchema               SchemaValidationField = "Schema"
	SchemaFieldKeyword              SchemaValidationField = "Keyword"
	SchemaFieldType                 SchemaValidationField = "Type"
	SchemaFieldProperties           SchemaValidationField = "Properties"
	SchemaFieldItems                SchemaValidationField = "Items"
	SchemaFieldEnum                 SchemaValidationField = "Enum"
	SchemaFieldRequired             SchemaValidationField = "Required"
	SchemaFieldAdditionalProperties SchemaValidationField = "AdditionalProperties"
	SchemaFieldOutput               SchemaValidationField = "Output"
)

type SchemaValidationReason

type SchemaValidationReason string

SchemaValidationReason identifies why an output-schema component failed validation. It intentionally contains no caller-provided content.

const (
	SchemaReasonEmpty             SchemaValidationReason = "empty"
	SchemaReasonInvalid           SchemaValidationReason = "invalid"
	SchemaReasonReserved          SchemaValidationReason = "reserved"
	SchemaReasonTooLong           SchemaValidationReason = "too long"
	SchemaReasonInvalidUTF8       SchemaValidationReason = "invalid UTF-8"
	SchemaReasonMalformed         SchemaValidationReason = "malformed"
	SchemaReasonTooLarge          SchemaValidationReason = "too large"
	SchemaReasonRootNotObject     SchemaValidationReason = "root is not an object schema"
	SchemaReasonUnknownKeyword    SchemaValidationReason = "unknown keyword"
	SchemaReasonMissing           SchemaValidationReason = "missing"
	SchemaReasonUnsupported       SchemaValidationReason = "unsupported"
	SchemaReasonMustBeFalse       SchemaValidationReason = "must be false"
	SchemaReasonDuplicate         SchemaValidationReason = "duplicate"
	SchemaReasonUnknownProperty   SchemaValidationReason = "unknown property"
	SchemaReasonTypeMismatch      SchemaValidationReason = "type mismatch"
	SchemaReasonTooDeep           SchemaValidationReason = "too deep"
	SchemaReasonTooManyProperties SchemaValidationReason = "too many properties"
	SchemaReasonInvalidTarget     SchemaValidationReason = "invalid target"
	SchemaReasonDecodeFailed      SchemaValidationReason = "decode failed"
)

type SessionIDProblem added in v0.13.0

type SessionIDProblem string

SessionIDProblem names why a Request.SessionID was refused.

const (
	// SessionIDUnsendableByte: a byte that cannot appear in an HTTP header
	// field value — CR, LF, NUL, any other C0 control except HTAB, or DEL.
	SessionIDUnsendableByte SessionIDProblem = "unsendable_byte"
	// SessionIDSurroundingWhitespace: a leading or trailing SP or HTAB. Go's
	// own HTTP/1.1 client trims it when writing the header (http.Header.Write),
	// and HTTP recipients strip optional whitespace around a field value (RFC
	// 9110 §5.5), so the identity would arrive upstream as a DIFFERENT value —
	// one that can collide with another conversation's.
	SessionIDSurroundingWhitespace SessionIDProblem = "surrounding_whitespace"
	// SessionIDTooLong: longer than MaxSessionIDBytes bytes.
	SessionIDTooLong SessionIDProblem = "too_long"
)

type StructuredOutputConflictError

type StructuredOutputConflictError struct {
	Feature string
}

StructuredOutputConflictError reports an invalid request feature combination. Feature is a bounded classification, never a schema or tool payload supplied by the caller.

func (*StructuredOutputConflictError) Error

type StructuredOutputFinishError

type StructuredOutputFinishError struct {
	Reason stream.FinishReason
}

StructuredOutputFinishError reports finish metadata that cannot safely produce the requested structured result.

func (*StructuredOutputFinishError) Error

type StructuredOutputUnsupportedError

type StructuredOutputUnsupportedError struct {
	Model string
}

StructuredOutputUnsupportedError reports that a model does not advertise native structured output. Model is diagnostic metadata only.

func (*StructuredOutputUnsupportedError) Error

type StructuredOutputWithToolsUnsupportedError

type StructuredOutputWithToolsUnsupportedError struct {
	Model string
}

StructuredOutputWithToolsUnsupportedError reports that a model does not advertise the distinct native structured-output-with-tools capability. Model is diagnostic metadata only.

func (*StructuredOutputWithToolsUnsupportedError) Error

type Tool

type Tool struct {
	Name        string
	Description string
	Schema      json.RawMessage
}

Tool is a callable function definition exposed to the model.

type ToolChoice

type ToolChoice struct {
	// contains filtered or unexported fields
}

ToolChoice controls whether the model may choose between text and tools, must call some tool, or must call one named tool.

It is an opaque comparable value built only by ToolAuto, ToolRequired and ToolNamed, so the forced tool name cannot be separated from the variant that gives it meaning: "named choice, no name" and "name, but not a named choice" are unspellable rather than merely validated. Carrying the name in a sibling Request field would make both reachable and would need a validation error code apiece to catch after the fact; keeping it inside the variant removes the states instead of policing them.

One cross-field invariant a type cannot encode remains, and is checked in ValidateRequestFeatures: a named choice whose name matches no declared tool. No provider schema enforces that either — measured across all five.

The zero value is ToolAuto(), so a Request struct literal that never mentions ToolChoice keeps the automatic behavior. That requirement is why this is a struct and not a sealed interface in the shape of content.Block: an interface has nil for a zero value, so "auto" would have two spellings and every consumer would need a nil arm — reintroducing exactly the kind of invalid state this type exists to remove.

A variant is added here, not by callers: the discriminant is unexported and the constructors are the only way in. A future multi-name allowlist (Gemini's allowedFunctionNames, OpenAI's allowed_tools) is therefore an additive change to this file — one mode, one field, one constructor — with the single cross-cutting cost that a slice-valued field would end ToolChoice's comparability with ==.

func ToolAuto

func ToolAuto() ToolChoice

ToolAuto lets the model choose between text and tools. It is the zero value.

func ToolNamed

func ToolNamed(name string) ToolChoice

ToolNamed forces the model to call the single tool called name, which the request must declare. Every dialect this module encodes has a wire form for it.

func ToolRequired

func ToolRequired() ToolChoice

ToolRequired forces the model to call some tool of its own choosing. The request must declare at least one tool.

func (ToolChoice) Mode

func (c ToolChoice) Mode() ToolChoiceMode

Mode reports which variant this choice is.

func (ToolChoice) Named

func (c ToolChoice) Named() (name string, ok bool)

Named reports the single tool the model must call. ok is false for every variant other than ToolChoiceModeNamed, so a caller cannot read a forced name out of a choice that does not force one.

func (ToolChoice) String

func (c ToolChoice) String() string

String renders the choice for diagnostics.

type ToolChoiceMode

type ToolChoiceMode uint8

ToolChoiceMode enumerates the tool-choice variants. It is the discriminant a codec switches on; it is not itself a choice, because two of the three variants carry no data and the third is meaningless without its tool name.

const (
	// ToolChoiceModeAuto lets the model decide between text and tools.
	ToolChoiceModeAuto ToolChoiceMode = iota
	// ToolChoiceModeRequired forces some tool call, leaving the model the choice
	// of which.
	ToolChoiceModeRequired
	// ToolChoiceModeNamed forces the one tool the choice names.
	ToolChoiceModeNamed
)

Directories

Path Synopsis
Package auth provides the legacy inference authorization facade.
Package auth provides the legacy inference authorization facade.
conformance
Package conformance is the schema conformance gate for provider wire fixtures.
Package conformance is the schema conformance gate for provider wire fixtures.
conformance/cmd/schemagen command
Command schemagen derives the checked-in JSON Schema 2020-12 documents that back the provider conformance gate.
Command schemagen derives the checked-in JSON Schema 2020-12 documents that back the provider conformance gate.
openairesponses
Package openairesponses is the OpenAI Responses API wire dialect (POST /v1/responses): a genuinely different, items-based shape from OpenAI Chat Completions (codec/openaiapi) — not a flat messages array.
Package openairesponses is the OpenAI Responses API wire dialect (POST /v1/responses): a genuinely different, items-based shape from OpenAI Chat Completions (codec/openaiapi) — not a flat messages array.
servertest
Package servertest provides a reusable contract suite for codec.ServerCodec implementations.
Package servertest provides a reusable contract suite for codec.ServerCodec implementations.
Package contextcount provides deterministic complete-request context counting.
Package contextcount provides deterministic complete-request context counting.
examples
gateway command
invoke command
retry command
stream command
Package failure owns provider-neutral inference failures shared by codecs, transports, and provider integrations.
Package failure owns provider-neutral inference failures shared by codecs, transports, and provider integrations.
Package gateway provides a local HTTP compatibility layer that lets coding-harness clients speaking different model-API dialects (Anthropic Messages, OpenAI Responses, OpenAI Chat Completions, Gemini) reach any injected inference.Client/model.Model target.
Package gateway provides a local HTTP compatibility layer that lets coding-harness clients speaking different model-API dialects (Anthropic Messages, OpenAI Responses, OpenAI Chat Completions, Gemini) reach any injected inference.Client/model.Model target.
Package inferencetest provides a scripted, in-memory inference.Client for running and testing agents without a provider, an API key or a network.
Package inferencetest provides a scripted, in-memory inference.Client for running and testing agents without a provider, an API key or a network.
internal
jsonstrict
Package jsonstrict provides a small, dialect-agnostic JSON scan used by every codec/*api server-decode path to reject a request body that smuggles a duplicate object member name.
Package jsonstrict provides a small, dialect-agnostic JSON scan used by every codec/*api server-decode path to reject a request body that smuggles a duplicate object member name.
usagenorm
Package usagenorm validates and normalizes provider token-usage wire values.
Package usagenorm validates and normalizes provider token-usage wire values.
Package retry decorates an inference.Client with bounded, classified retry and exponential backoff.
Package retry decorates an inference.Client with bounded, classified retry and exponential backoff.
Package route holds concrete route.Router builders for the bundled wire APIs: a static chat route (OpenAI/Anthropic style) and Gemini's mode-aware model-in-path route.
Package route holds concrete route.Router builders for the bundled wire APIs: a static chat route (OpenAI/Anthropic style) and Gemini's mode-aware model-in-path route.
Package transport is a generic, connection-bound HTTP client for the inference seam.
Package transport is a generic, connection-bound HTTP client for the inference seam.
wire
eventstream
Package eventstream frames AWS Event Stream messages into raw inference stream frames.
Package eventstream frames AWS Event Stream messages into raw inference stream frames.
jsonbody
Package jsonbody holds small stdlib helpers for JSON HTTP bodies: marshal a value into a request-body reader (with its content type) and unmarshal response bytes back into a value.
Package jsonbody holds small stdlib helpers for JSON HTTP bodies: marshal a value into a request-body reader (with its content type) and unmarshal response bytes back into a value.
ndjson
Package ndjson frames a newline-delimited JSON body into one raw stream frame per line: StreamFrame.Data is the line's bytes and Name is empty.
Package ndjson frames a newline-delimited JSON body into one raw stream frame per line: StreamFrame.Data is the line's bytes and Name is empty.
sse
Package sse is a real Server-Sent Events event framer (WHATWG event stream model), not an OpenAI-only "data: " line stripper.
Package sse is a real Server-Sent Events event framer (WHATWG event stream model), not an OpenAI-only "data: " line stripper.

Jump to

Keyboard shortcuts

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