openairesponses

package
v0.12.1 Latest Latest
Warning

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

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

Documentation

Overview

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. It is both a client-side codec.StreamingCodec (neutral -> wire, for calling a Responses-speaking target) and a server-side codec.ServerCodec (wire -> neutral, for serving a Responses-speaking harness such as Codex).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeResponse

func DecodeResponse(body []byte) (*inference.Response, error)

DecodeResponse parses a non-streaming OpenAI Responses API response body into a provider-neutral *inference.Response. A status:"failed" response is surfaced as a *failure.APIError, mirroring how anthropicapi.DecodeResponse handles its type:"error" envelope. An empty output array is a valid response, not an error.

func EncodeRequest

func EncodeRequest(req inference.Request, stream bool) ([]byte, error)

EncodeRequest converts a provider-neutral inference.Request into an OpenAI Responses `POST /v1/responses` JSON body. stream=true adds "stream":true to the body. Request.System (plus any in-thread SystemMessage) becomes the top-level `instructions` field: Responses has no in-thread system role, so a SystemMessage folds into instructions exactly as anthropicapi folds it into the top-level `system` field.

Types

type Codec

type Codec struct{}

Codec is the OpenAI Responses API wire dialect expressed as a codec.Codec (and, via DecodeStream in stream.go, a codec.StreamingCodec) AND, unlike codec/openaiapi today, a full codec.ServerCodec: this package is built from scratch with both directions, since unlike Anthropic there is no prior client-only package to extend. It is stateless (an empty struct with value-receiver methods), so one value is safely shared across goroutines. The methods delegate to package-level free functions so the method surface and the free surface cannot diverge.

func (Codec) DecodeEvent

func (Codec) DecodeEvent(event []byte) ([]content.Chunk, error)

DecodeEvent decodes one already-de-framed SSE event payload into the chunk(s) it yields. It is stateless: unknown valid event types are skipped, while malformed JSON is an error. Cross-event assembly (concatenating a tool call's argument fragments, or a reasoning summary's text fragments) happens downstream in the stream accumulator, not here.

func (Codec) DecodeRequest

func (Codec) DecodeRequest(req *http.Request) (codec.DecodedRequest, error)

DecodeRequest decodes a matched POST /v1/responses request into a codec.DecodedRequest, delegating to the free decodeResponsesRequest.

func (Codec) DecodeResponse

func (Codec) DecodeResponse(body []byte) (*inference.Response, error)

DecodeResponse parses a non-streaming Responses response body, delegating to the free DecodeResponse.

func (Codec) DecodeStream

func (Codec) DecodeStream(resp *http.Response) (*stream.StreamReader[content.Chunk], error)

DecodeStream frames a successful Responses streaming response with wire/sse and maps each frame through the codec's per-event decode logic. Unlike Chat Completions there is no explicit [DONE] sentinel: the stream ends when response.completed's terminal metadata has been observed and the body reaches natural EOF, matching how anthropicapi relies on message_stop plus EOF rather than a sentinel. An EOF that arrives without a terminal response event fails with a *StreamDecodeError rather than reporting a clean, truncated success. It owns resp.Body: the returned reader's Close closes it.

func (Codec) EncodeRequest

func (Codec) EncodeRequest(req inference.Request, mode codec.RequestMode) (codec.EncodedRequest, error)

EncodeRequest builds the Responses request: a JSON body reader plus the application/json content type as an EncodedRequest. RequestModeStream sets "stream":true in the body, every other mode omits it.

func (Codec) MatchRequest

func (Codec) MatchRequest(req *http.Request) bool

MatchRequest reports whether req is a POST /v1/responses request.

func (Codec) OpenStream

func (Codec) OpenStream(w http.ResponseWriter) (codec.StreamEncoder, error)

OpenStream begins the native Responses streaming response and returns its request-scoped StreamEncoder, delegating to the free openResponsesStream.

func (Codec) WriteError

func (Codec) WriteError(w http.ResponseWriter, err error)

WriteError encodes err as the native Responses error envelope, delegating to the free writeResponsesError.

func (Codec) WriteResponse

func (Codec) WriteResponse(w http.ResponseWriter, resp *inference.Response) error

WriteResponse encodes a complete inference.Response as the native Responses API non-streaming response, delegating to the free writeResponsesResponse.

type DuplicateKeyError

type DuplicateKeyError struct {
	Key string
}

DuplicateKeyError reports a request body with a duplicate JSON object member name. encoding/json silently takes the last occurrence; this codec rejects the request instead so a client cannot smuggle a semantically different value past a naive review of the first occurrence.

func (*DuplicateKeyError) Error

func (e *DuplicateKeyError) Error() string

type SamplingRangeError

type SamplingRangeError struct {
	Field string
	Value float64
	Min   float64
	Max   float64
}

SamplingRangeError is returned by the encoder when a sampling knob falls outside the interval CreateResponse declares for it — temperature [0, 2], top_p [0, 1], reached through CreateModelResponseProperties -> ModelResponseProperties, the same schema Chat Completions inherits.

Min and Max are carried on the error rather than baked into the message because the two fields have DIFFERENT bounds here, and because the bound that matters is the destination's: Anthropic and Bedrock cap temperature at 1 and OpenAI at 2, so a session moved between providers carries a value that was legal at its source into a request where it is not. The shared model.Sampling vocabulary is wide enough to hold every dialect's range, so the narrowing has to happen in the codec that owns the destination contract. This mirrors the sibling openaiapi error of the same name.

func (*SamplingRangeError) Error

func (e *SamplingRangeError) Error() string

type ServerDecodeError

type ServerDecodeError struct {
	Reason string
	Detail string
}

ServerDecodeError reports a native Responses request body this codec cannot decode into the provider-neutral vocabulary: malformed shape, a missing required field, or a recognized-but-unsupported feature. Reason is a short machine-checkable diagnostic code; Detail elaborates for logs/messages.

func (*ServerDecodeError) Error

func (e *ServerDecodeError) Error() string

type StreamAPIError

type StreamAPIError struct {
	Code    string
	Message string
}

StreamAPIError reports a native `response.failed` event received after a streaming request crossed the successful HTTP-status boundary. It retains only the provider's structured error code and message, never the raw response frame.

func (*StreamAPIError) Error

func (e *StreamAPIError) Error() string

type StreamDecodeError

type StreamDecodeError struct {
	Reason string
	Err    error
}

StreamDecodeError reports a Responses stream that is framed and parseable but structurally wrong — currently only a body that reaches EOF without one of the union's terminal response events (response.completed or response.incomplete; response.failed and the top-level error event abort with a *StreamAPIError instead), which means the answer was truncated in flight. It never includes the raw provider payload in its diagnostic. Named and shaped after the equivalent type in codec/bedrockconverse and codec/geminiapi. It lives here rather than in errors.go because the gate it serves is the only thing that raises it.

func (*StreamDecodeError) Error

func (e *StreamDecodeError) Error() string

func (*StreamDecodeError) Unwrap

func (e *StreamDecodeError) Unwrap() error

type StreamEventDecodeError

type StreamEventDecodeError struct{ Err error }

StreamEventDecodeError reports malformed JSON inside an otherwise successfully framed Responses stream. Unknown well-formed events remain forward-compatible skips.

func (*StreamEventDecodeError) Error

func (e *StreamEventDecodeError) Error() string

func (*StreamEventDecodeError) Unwrap

func (e *StreamEventDecodeError) Unwrap() error

type StreamTerminatedError

type StreamTerminatedError struct{}

StreamTerminatedError is returned by StreamEncoder.WriteChunk, Finish, or Fail once the stream has already been terminated by a prior Finish or Fail call, per the single-termination-ownership rule in codec.StreamEncoder.

func (*StreamTerminatedError) Error

func (e *StreamTerminatedError) Error() string

type UnsupportedBlockError

type UnsupportedBlockError struct {
	Block  string
	Reason string
}

UnsupportedBlockError is returned by an encoder when a content block cannot be placed on the wire: a concrete type this dialect does not model in that position (audio anywhere, any non-text block in a text-only tool result), or a block whose value the position's schema cannot carry (a document with no name to attach its inline data to). Block holds the Go type name for diagnosis; Reason, when set, names the specific limitation — mirroring the sibling bedrockconverse and openaiapi codecs' errors of the same name.

func (*UnsupportedBlockError) Error

func (e *UnsupportedBlockError) Error() string

type UnsupportedChunkError

type UnsupportedChunkError struct {
	Chunk string
}

UnsupportedChunkError is returned when a content.Chunk has a concrete type this dialect's stream encoder does not model. content.Chunk is a sealed interface, so this only guards against future variants added to the vocabulary.

func (*UnsupportedChunkError) Error

func (e *UnsupportedChunkError) Error() string

type UnsupportedConversationError

type UnsupportedConversationError struct {
	Conversation string
}

UnsupportedConversationError is returned by the encoder when a conversation turn has a concrete type outside the closed content.Conversation union the dialect maps (user / assistant / tool-result / system). Conversation holds the Go type name for diagnosis.

func (*UnsupportedConversationError) Error

Jump to

Keyboard shortcuts

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