Documentation
¶
Index ¶
- Constants
- Variables
- func AdaptEmbeddingRequest(registry *Registry, body []byte, source, target Format) ([]byte, error)
- func AdaptEmbeddingResponse(registry *Registry, body []byte, source, target Format) ([]byte, error)
- func AdaptRerankRequest(registry *Registry, body []byte, source, target Format) ([]byte, error)
- func AdaptRerankResponse(registry *Registry, body []byte, source, target Format) ([]byte, error)
- func BodyCarriesRetryableError(body []byte) bool
- func EnforceModel(body []byte, allowedModels []string, defaultModel string) ([]byte, string, error)
- func ExtractAssistantOutputGeneric(body []byte) string
- func ExtractModel(body []byte) (string, error)
- func ExtractModelField(body []byte) (model string, hasModelID bool, err error)
- func ExtractUserInputGeneric(body []byte) string
- func GeminiModelFromPath(path string) string
- func IsRequestDecodeError(err error) bool
- func IsSameWireFormat(a, b Format) bool
- func NormalizeGroqRequest(body []byte) []byte
- func NormalizeOpenAIRequest(body []byte) []byte
- func NormalizeRequestForProvider(providerName string, targetFormat Format, body []byte) []byte
- func OverrideModel(body []byte, model string) []byte
- func RequestWantsStream(body []byte) (stream bool, explicit bool)
- func SSEData(dataJSON []byte) [][]byte
- func SSEEvent(eventType string, dataJSON []byte) [][]byte
- func ShouldPassthroughSameWireFormat(source, target Format) bool
- func StripModel(body []byte) []byte
- func SupportedSourceFormat(f Format) bool
- type AnthropicAdapter
- func (a *AnthropicAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *AnthropicAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *AnthropicAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *AnthropicAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *AnthropicAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *AnthropicAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type BedrockAdapter
- func (a *BedrockAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *BedrockAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *BedrockAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *BedrockAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *BedrockAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *BedrockAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type CanonicalEmbeddingRequest
- type CanonicalEmbeddingResponse
- type CanonicalMessage
- type CanonicalReasoning
- type CanonicalRequest
- type CanonicalRespFormat
- type CanonicalResponse
- type CanonicalStreamChunk
- type CanonicalTool
- type CanonicalToolCall
- type CanonicalToolChoice
- type CanonicalUsage
- type CohereAdapter
- func (a *CohereAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *CohereAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *CohereAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *CohereAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *CohereAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *CohereAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type CohereEmbedAdapter
- func (a *CohereEmbedAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *CohereEmbedAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *CohereEmbedAdapter) DecodeStreamChunk([]byte) (*CanonicalStreamChunk, error)
- func (a *CohereEmbedAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *CohereEmbedAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *CohereEmbedAdapter) EncodeStreamChunk(*CanonicalStreamChunk) ([][]byte, error)
- type CohereRerankAdapter
- func (a *CohereRerankAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *CohereRerankAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *CohereRerankAdapter) DecodeStreamChunk([]byte) (*CanonicalStreamChunk, error)
- func (a *CohereRerankAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *CohereRerankAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *CohereRerankAdapter) EncodeStreamChunk(*CanonicalStreamChunk) ([][]byte, error)
- type Format
- func DetectFormat(body []byte) Format
- func ResolveAgentFormat(providerName, sourceFormat string, providerOptions map[string]any) (Format, error)
- func ResolveTargetFormat(providerName string, providerOptions map[string]any) Format
- func ResolveTargetFormatForCapability(providerName string, capability string, providerOptions map[string]any) Format
- type GeminiAdapter
- func (a *GeminiAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *GeminiAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *GeminiAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *GeminiAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *GeminiAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *GeminiAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type MistralAdapter
- func (a *MistralAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *MistralAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *MistralAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *MistralAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *MistralAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *MistralAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type OpenAIAdapter
- func (a *OpenAIAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *OpenAIAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *OpenAIAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *OpenAIAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *OpenAIAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *OpenAIAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type OpenAIEmbeddingsAdapter
- func (a *OpenAIEmbeddingsAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *OpenAIEmbeddingsAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *OpenAIEmbeddingsAdapter) DecodeStreamChunk([]byte) (*CanonicalStreamChunk, error)
- func (a *OpenAIEmbeddingsAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *OpenAIEmbeddingsAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *OpenAIEmbeddingsAdapter) EncodeStreamChunk(*CanonicalStreamChunk) ([][]byte, error)
- type OpenAIResponsesAdapter
- func (a *OpenAIResponsesAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *OpenAIResponsesAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *OpenAIResponsesAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *OpenAIResponsesAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *OpenAIResponsesAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *OpenAIResponsesAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type OpenRouterAdapter
- func (a *OpenRouterAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
- func (a *OpenRouterAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
- func (a *OpenRouterAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
- func (a *OpenRouterAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
- func (a *OpenRouterAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
- func (a *OpenRouterAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
- type ProviderAdapter
- type Registry
- func (r *Registry) AdaptRequest(body []byte, source, target Format) ([]byte, error)
- func (r *Registry) AdaptResponse(body []byte, source, target Format) ([]byte, error)
- func (r *Registry) AdaptStreamChunk(chunk []byte, source, target Format) ([][]byte, error)
- func (r *Registry) DecodeRequestFor(body []byte, providerFormat Format) (*CanonicalRequest, error)
- func (r *Registry) DecodeResponseFor(body []byte, providerFormat Format) (*CanonicalResponse, error)
- func (r *Registry) DecodeStreamChunkFor(chunk []byte, target Format) (*CanonicalStreamChunk, error)
- func (r *Registry) EncodeStreamChunkFor(canonical *CanonicalStreamChunk, source Format) ([][]byte, error)
- func (r *Registry) GetAdapter(f Format) (ProviderAdapter, error)
- func (r *Registry) Register(f Format, a ProviderAdapter)
- type RequestAdapter
- type RequestDecodeError
- type ResponseAdapter
- type StreamAdapter
- type StreamToolCallDelta
Constants ¶
const GeminiModelsRoutePrefix = "/v1beta/models/"
GeminiModelsRoutePrefix is the fixed Gemini route segment that carries the model in the URL instead of the body.
const MetadataUsageKey = "usage"
MetadataUsageKey is the RequestContext.Metadata key under which the streaming usage observer records the latest *CanonicalUsage. The metrics pipeline reads it back from the same key when building the exchange.
Variables ¶
var ErrModelNotAllowed = errors.New("model not allowed")
Functions ¶
func AdaptEmbeddingRequest ¶ added in v0.3.4
func AdaptEmbeddingResponse ¶ added in v0.3.4
func AdaptRerankRequest ¶ added in v0.3.4
func AdaptRerankResponse ¶ added in v0.3.4
func EnforceModel ¶
func ExtractAssistantOutputGeneric ¶
ExtractAssistantOutputGeneric attempts to find assistant output from common JSON fields when no provider-specific adapter is available. It probes, in order: choices[0].message.content, content, output.
func ExtractModel ¶
func ExtractModelField ¶
func ExtractUserInputGeneric ¶
ExtractUserInputGeneric attempts to find user input from common JSON fields when no provider-specific adapter is available. It probes, in order: messages[-1].content (last user), input, prompt.
func GeminiModelFromPath ¶
GeminiModelFromPath extracts the model segment of a Gemini generateContent path, e.g. "/v1beta/models/gemini-pro:generateContent" -> "gemini-pro".
func IsRequestDecodeError ¶
IsRequestDecodeError returns true when err (or any error in its chain) is a RequestDecodeError, i.e. the caller sent a body that does not match the expected provider format.
func IsSameWireFormat ¶
func NormalizeGroqRequest ¶
NormalizeGroqRequest applies OpenAI-compatible fixes plus Groq-specific request normalizations before calling the Groq API. It does not alter upstream error responses.
Groq-specific normalizations:
- Ensures tools[].type is "function" when the tools array is present.
- Sets parallel_tool_calls to false when tools are used and the field is omitted (reduces tool_use_failed on some Llama models).
- Drops assistant history messages that only contain Llama-style <function=...> text without structured tool_calls (poisoned turns from clients or prior failed generations).
func NormalizeOpenAIRequest ¶
NormalizeOpenAIRequest performs lightweight, in-place normalization of an OpenAI-compatible request body to fix common issues sent by third-party SDKs (e.g. Mistral, Cohere) that use the OpenAI wire format but omit fields that OpenAI strictly requires.
Current normalizations:
- Ensures every tool_call object inside messages has "type": "function". The Mistral SDK omits this field, but OpenAI returns 400 without it.
- Ensures every tools[].function.parameters is a non-empty JSON Schema object. Gemini cross-format requests often omit parameters; strict OpenAI-wire upstreams (e.g. Cerebras gpt-oss) reject tools without it.
The function is a no-op (returns the original body) when no changes are needed, so it is safe to call unconditionally on every OpenAI-bound request.
func NormalizeRequestForProvider ¶
NormalizeRequestForProvider applies provider-specific request fixes before an upstream call. Groq uses NormalizeGroqRequest; other OpenAI-wire targets use NormalizeOpenAIRequest when applicable.
func OverrideModel ¶
func RequestWantsStream ¶
func SSEData ¶
SSEData builds a single "data: …" line followed by an empty separator. This is the format used by providers that do not emit "event:" lines (e.g. OpenAI, Azure).
func SSEEvent ¶
SSEEvent builds the standard SSE lines for one event:
event: <eventType> data: <dataJSON> <empty line>
The caller writes each element followed by "\n".
func ShouldPassthroughSameWireFormat ¶
ShouldPassthroughSameWireFormat reports whether request/response bodies can be forwarded without canonical adaptation. Groq and OpenRouter are OpenAI-compatible but not identical, so openai↔groq/openrouter still goes through the adapter.
func StripModel ¶
func SupportedSourceFormat ¶
Types ¶
type AnthropicAdapter ¶
type AnthropicAdapter struct{}
AnthropicAdapter converts between Anthropic Messages API format and the canonical internal model.
func (*AnthropicAdapter) DecodeRequest ¶
func (a *AnthropicAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*AnthropicAdapter) DecodeResponse ¶
func (a *AnthropicAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*AnthropicAdapter) DecodeStreamChunk ¶
func (a *AnthropicAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*AnthropicAdapter) EncodeRequest ¶
func (a *AnthropicAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*AnthropicAdapter) EncodeResponse ¶
func (a *AnthropicAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*AnthropicAdapter) EncodeStreamChunk ¶
func (a *AnthropicAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type BedrockAdapter ¶
type BedrockAdapter struct {
// contains filtered or unexported fields
}
BedrockAdapter converts between AWS Bedrock model-specific formats and the canonical internal model. Bedrock hosts multiple model families (Claude, Titan, Llama, Mistral, DeepSeek/OpenAI-compat) each with its own wire format. This adapter dispatches to the appropriate sub-adapter based on model family detection.
func (*BedrockAdapter) DecodeRequest ¶
func (a *BedrockAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*BedrockAdapter) DecodeResponse ¶
func (a *BedrockAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*BedrockAdapter) DecodeStreamChunk ¶
func (a *BedrockAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*BedrockAdapter) EncodeRequest ¶
func (a *BedrockAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*BedrockAdapter) EncodeResponse ¶
func (a *BedrockAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*BedrockAdapter) EncodeStreamChunk ¶
func (a *BedrockAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type CanonicalEmbeddingRequest ¶ added in v0.3.4
type CanonicalEmbeddingResponse ¶ added in v0.3.4
type CanonicalEmbeddingResponse struct {
Model string `json:"model,omitempty"`
Embeddings [][]float64 `json:"embeddings,omitempty"`
Usage *CanonicalUsage `json:"usage,omitempty"`
}
type CanonicalMessage ¶
type CanonicalMessage struct {
Role string `json:"role"`
Content string `json:"content"`
ToolCalls []CanonicalToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
CanonicalMessage represents a single turn in the conversation.
type CanonicalReasoning ¶
type CanonicalReasoning struct {
Effort []byte `json:"effort,omitempty"` // OpenAI: provider-specific (e.g. JSON)
Summary *string `json:"summary,omitempty"` // OpenAI: summary
ThinkingText string `json:"thinking_text,omitempty"` // Anthropic/Gemini: raw thinking blocks concatenated
}
CanonicalReasoning holds optional reasoning/thinking metadata from the model. OpenAI uses Effort/Summary; Anthropic/Gemini use ThinkingText (raw thinking content).
type CanonicalRequest ¶
type CanonicalRequest struct {
Model string `json:"model,omitempty"`
System string `json:"system,omitempty"`
Messages []CanonicalMessage `json:"messages,omitempty"`
Tools []CanonicalTool `json:"tools,omitempty"`
ToolChoice *CanonicalToolChoice `json:"tool_choice,omitempty"`
MaxTokens int `json:"max_tokens,omitempty"`
Temperature *float64 `json:"temperature,omitempty"`
TopP *float64 `json:"top_p,omitempty"`
TopK *int `json:"top_k,omitempty"`
Stop []string `json:"stop,omitempty"`
Stream bool `json:"stream,omitempty"`
ResponseFormat *CanonicalRespFormat `json:"response_format,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
RequestExtensions map[string]json.RawMessage `json:"request_extensions,omitempty"`
}
CanonicalRequest is the internal neutral representation of any AI provider
type CanonicalRespFormat ¶
type CanonicalRespFormat struct {
Type string `json:"type"` // "json_object", "text"
}
CanonicalRespFormat controls the response format.
type CanonicalResponse ¶
type CanonicalResponse struct {
ID string `json:"id,omitempty"`
Model string `json:"model,omitempty"`
Content string `json:"content,omitempty"`
Role string `json:"role,omitempty"`
ToolCalls []CanonicalToolCall `json:"tool_calls,omitempty"`
FinishReason string `json:"finish_reason,omitempty"` // "stop", "length", "tool_calls"
Usage *CanonicalUsage `json:"usage,omitempty"`
Reasoning *CanonicalReasoning `json:"reasoning,omitempty"` // e.g. OpenAI reasoning / thinking
ProviderExtensions map[string]json.RawMessage `json:"provider_extensions,omitempty"`
}
CanonicalResponse is the internal neutral representation of a provider response.
type CanonicalStreamChunk ¶
type CanonicalStreamChunk struct {
ID string `json:"id,omitempty"`
Model string `json:"model,omitempty"`
Role string `json:"role,omitempty"` // only on first chunk
Delta string `json:"delta,omitempty"` // text content delta
FinishReason string `json:"finish_reason,omitempty"`
ToolCallDeltas []StreamToolCallDelta `json:"tool_call_deltas,omitempty"`
Usage *CanonicalUsage `json:"usage,omitempty"` // present in the final chunk of some providers
ProviderExtensions map[string]json.RawMessage `json:"provider_extensions,omitempty"`
}
CanonicalStreamChunk is one piece of a streamed response.
type CanonicalTool ¶
type CanonicalTool struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Schema map[string]interface{} `json:"schema,omitempty"`
}
CanonicalTool represents a tool/function the model can call.
type CanonicalToolCall ¶
type CanonicalToolCall struct {
ID string `json:"id"`
Name string `json:"name"`
Arguments string `json:"arguments"` // raw JSON string
}
CanonicalToolCall represents a tool invocation by the model.
type CanonicalToolChoice ¶
type CanonicalToolChoice struct {
// Type: "auto", "none", "any", "tool"
Type string `json:"type"`
// Name is only set when Type == "tool"
Name string `json:"name,omitempty"`
}
CanonicalToolChoice controls how the model selects tools.
type CanonicalUsage ¶
type CanonicalUsage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
TotalTokens int `json:"total_tokens"`
// Provider-specific cache/billing fields (pass-through).
CacheCreationInputTokens int `json:"cache_creation_input_tokens,omitempty"`
CacheReadInputTokens int `json:"cache_read_input_tokens,omitempty"`
ServiceTier string `json:"service_tier,omitempty"`
CachedInputTokens int `json:"cached_input_tokens,omitempty"` // sub-count of InputTokens
ReasoningOutputTokens int `json:"reasoning_output_tokens,omitempty"` // sub-count of OutputTokens
ToolUseInputTokens int `json:"tool_use_input_tokens,omitempty"` // sub-count of InputTokens
}
CanonicalUsage holds token counts in a provider-neutral split: Input / Output / Total. The three buckets are the canonical view; sub-counts are optional refinements of InputTokens / OutputTokens (NOT subtracted from the totals). The nil-on-absence and total-synthesis contracts live in newCanonicalUsage.
type CohereAdapter ¶ added in v0.3.4
type CohereAdapter struct{}
func (*CohereAdapter) DecodeRequest ¶ added in v0.3.4
func (a *CohereAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*CohereAdapter) DecodeResponse ¶ added in v0.3.4
func (a *CohereAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*CohereAdapter) DecodeStreamChunk ¶ added in v0.3.4
func (a *CohereAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*CohereAdapter) EncodeRequest ¶ added in v0.3.4
func (a *CohereAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*CohereAdapter) EncodeResponse ¶ added in v0.3.4
func (a *CohereAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*CohereAdapter) EncodeStreamChunk ¶ added in v0.3.4
func (a *CohereAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type CohereEmbedAdapter ¶ added in v0.3.4
type CohereEmbedAdapter struct{}
func (*CohereEmbedAdapter) DecodeRequest ¶ added in v0.3.4
func (a *CohereEmbedAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*CohereEmbedAdapter) DecodeResponse ¶ added in v0.3.4
func (a *CohereEmbedAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*CohereEmbedAdapter) DecodeStreamChunk ¶ added in v0.3.4
func (a *CohereEmbedAdapter) DecodeStreamChunk([]byte) (*CanonicalStreamChunk, error)
func (*CohereEmbedAdapter) EncodeRequest ¶ added in v0.3.4
func (a *CohereEmbedAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*CohereEmbedAdapter) EncodeResponse ¶ added in v0.3.4
func (a *CohereEmbedAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*CohereEmbedAdapter) EncodeStreamChunk ¶ added in v0.3.4
func (a *CohereEmbedAdapter) EncodeStreamChunk(*CanonicalStreamChunk) ([][]byte, error)
type CohereRerankAdapter ¶ added in v0.3.4
type CohereRerankAdapter struct{}
CohereRerankAdapter maps gateway /v1/rerank payloads to Cohere v2 rerank wire format. The gateway speaks the same JSON shape as Cohere v2 rerank, so encode/decode are identity.
func (*CohereRerankAdapter) DecodeRequest ¶ added in v0.3.4
func (a *CohereRerankAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*CohereRerankAdapter) DecodeResponse ¶ added in v0.3.4
func (a *CohereRerankAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*CohereRerankAdapter) DecodeStreamChunk ¶ added in v0.3.4
func (a *CohereRerankAdapter) DecodeStreamChunk([]byte) (*CanonicalStreamChunk, error)
func (*CohereRerankAdapter) EncodeRequest ¶ added in v0.3.4
func (a *CohereRerankAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*CohereRerankAdapter) EncodeResponse ¶ added in v0.3.4
func (a *CohereRerankAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*CohereRerankAdapter) EncodeStreamChunk ¶ added in v0.3.4
func (a *CohereRerankAdapter) EncodeStreamChunk(*CanonicalStreamChunk) ([][]byte, error)
type Format ¶
type Format string
const ( FormatOpenAI Format = "openai" FormatOpenAIResponses Format = "openai_responses" FormatAnthropic Format = "anthropic" FormatGemini Format = "google" FormatBedrock Format = "bedrock" FormatAzure Format = "azure" // wire-compatible with OpenAI FormatGroq Format = "groq" // wire-compatible with OpenAI Chat Completions FormatVertex Format = "vertex" FormatMistral Format = "mistral" FormatDeepSeek Format = "deepseek" // wire-compatible with OpenAI Chat Completions FormatXAI Format = "xai" // wire-compatible with OpenAI Chat Completions FormatOpenRouter Format = "openrouter" // wire-compatible with OpenAI Chat Completions FormatCohere Format = "cohere" FormatOpenAIEmbeddings Format = "openai_embeddings" FormatCohereEmbed Format = "cohere_embed" FormatCohereRerank Format = "cohere_rerank" )
func DetectFormat ¶
func ResolveAgentFormat ¶
func ResolveTargetFormat ¶
func ResolveTargetFormatForCapability ¶ added in v0.3.4
func ResolveTargetFormatForCapability(providerName string, capability string, providerOptions map[string]any) Format
ResolveTargetFormatForCapability picks the provider wire format for a proxy capability.
func (Format) IsOpenAIFamily ¶ added in v0.3.4
IsOpenAIFamily reports whether the format speaks an OpenAI-compatible wire protocol: Chat Completions (openai, azure, groq, deepseek) or the Responses API.
func (Format) SupportsCanonicalToolCalls ¶ added in v0.3.4
SupportsCanonicalToolCalls reports whether a response in this wire format can carry tool calls the gateway knows how to translate into the caller's format.
type GeminiAdapter ¶
type GeminiAdapter struct{}
GeminiAdapter converts between Google Gemini generateContent format and the canonical internal model.
func (*GeminiAdapter) DecodeRequest ¶
func (a *GeminiAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*GeminiAdapter) DecodeResponse ¶
func (a *GeminiAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*GeminiAdapter) DecodeStreamChunk ¶
func (a *GeminiAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*GeminiAdapter) EncodeRequest ¶
func (a *GeminiAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*GeminiAdapter) EncodeResponse ¶
func (a *GeminiAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*GeminiAdapter) EncodeStreamChunk ¶
func (a *GeminiAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type MistralAdapter ¶
type MistralAdapter struct {
// contains filtered or unexported fields
}
func (*MistralAdapter) DecodeRequest ¶
func (a *MistralAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*MistralAdapter) DecodeResponse ¶
func (a *MistralAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*MistralAdapter) DecodeStreamChunk ¶
func (a *MistralAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*MistralAdapter) EncodeRequest ¶
func (a *MistralAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*MistralAdapter) EncodeResponse ¶
func (a *MistralAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*MistralAdapter) EncodeStreamChunk ¶
func (a *MistralAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type OpenAIAdapter ¶
type OpenAIAdapter struct{}
OpenAIAdapter converts between OpenAI Chat Completions API format and the canonical internal model. It also acts as a dispatcher that auto-detects Responses API payloads and delegates decoding to the appropriate sub-adapter. Encoding always produces Chat Completions format; use OpenAIResponsesAdapter when Responses API encoding is needed.
func (*OpenAIAdapter) DecodeRequest ¶
func (a *OpenAIAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*OpenAIAdapter) DecodeResponse ¶
func (a *OpenAIAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*OpenAIAdapter) DecodeStreamChunk ¶
func (a *OpenAIAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*OpenAIAdapter) EncodeRequest ¶
func (a *OpenAIAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*OpenAIAdapter) EncodeResponse ¶
func (a *OpenAIAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*OpenAIAdapter) EncodeStreamChunk ¶
func (a *OpenAIAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type OpenAIEmbeddingsAdapter ¶ added in v0.3.4
type OpenAIEmbeddingsAdapter struct{}
func (*OpenAIEmbeddingsAdapter) DecodeRequest ¶ added in v0.3.4
func (a *OpenAIEmbeddingsAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*OpenAIEmbeddingsAdapter) DecodeResponse ¶ added in v0.3.4
func (a *OpenAIEmbeddingsAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*OpenAIEmbeddingsAdapter) DecodeStreamChunk ¶ added in v0.3.4
func (a *OpenAIEmbeddingsAdapter) DecodeStreamChunk([]byte) (*CanonicalStreamChunk, error)
func (*OpenAIEmbeddingsAdapter) EncodeRequest ¶ added in v0.3.4
func (a *OpenAIEmbeddingsAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*OpenAIEmbeddingsAdapter) EncodeResponse ¶ added in v0.3.4
func (a *OpenAIEmbeddingsAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*OpenAIEmbeddingsAdapter) EncodeStreamChunk ¶ added in v0.3.4
func (a *OpenAIEmbeddingsAdapter) EncodeStreamChunk(*CanonicalStreamChunk) ([][]byte, error)
type OpenAIResponsesAdapter ¶
type OpenAIResponsesAdapter struct{}
OpenAIResponsesAdapter converts between OpenAI Responses API format and the canonical internal model. Registered under FormatOpenAIResponses so that the cross-provider pipeline (AdaptRequest/AdaptResponse/AdaptStreamChunk) automatically produces Responses API wire format for the client.
func (*OpenAIResponsesAdapter) DecodeRequest ¶
func (a *OpenAIResponsesAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*OpenAIResponsesAdapter) DecodeResponse ¶
func (a *OpenAIResponsesAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*OpenAIResponsesAdapter) DecodeStreamChunk ¶
func (a *OpenAIResponsesAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*OpenAIResponsesAdapter) EncodeRequest ¶
func (a *OpenAIResponsesAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*OpenAIResponsesAdapter) EncodeResponse ¶
func (a *OpenAIResponsesAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*OpenAIResponsesAdapter) EncodeStreamChunk ¶
func (a *OpenAIResponsesAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type OpenRouterAdapter ¶ added in v0.3.4
type OpenRouterAdapter struct {
// contains filtered or unexported fields
}
OpenRouterAdapter wraps OpenAIAdapter and preserves OpenRouter routing fields.
func (*OpenRouterAdapter) DecodeRequest ¶ added in v0.3.4
func (a *OpenRouterAdapter) DecodeRequest(body []byte) (*CanonicalRequest, error)
func (*OpenRouterAdapter) DecodeResponse ¶ added in v0.3.4
func (a *OpenRouterAdapter) DecodeResponse(body []byte) (*CanonicalResponse, error)
func (*OpenRouterAdapter) DecodeStreamChunk ¶ added in v0.3.4
func (a *OpenRouterAdapter) DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
func (*OpenRouterAdapter) EncodeRequest ¶ added in v0.3.4
func (a *OpenRouterAdapter) EncodeRequest(req *CanonicalRequest) ([]byte, error)
func (*OpenRouterAdapter) EncodeResponse ¶ added in v0.3.4
func (a *OpenRouterAdapter) EncodeResponse(resp *CanonicalResponse) ([]byte, error)
func (*OpenRouterAdapter) EncodeStreamChunk ¶ added in v0.3.4
func (a *OpenRouterAdapter) EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
type ProviderAdapter ¶
type ProviderAdapter interface {
RequestAdapter
ResponseAdapter
StreamAdapter
}
ProviderAdapter combines all three conversion interfaces.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds provider adapters and exposes methods for cross-provider format adaptation. Unlike a global map+init(), a Registry is explicitly constructed and injected, making it testable and configurable.
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry creates a Registry pre-populated with all built-in adapters.
func (*Registry) AdaptRequest ¶
func (*Registry) AdaptResponse ¶
AdaptResponse transforms a provider response from targetFormat back to sourceFormat via the canonical model: target.DecodeResponse → canonical → source.EncodeResponse.
If the two formats are wire-compatible the body is returned unmodified, except when provider-specific extensions require canonical filtering.
func (*Registry) AdaptStreamChunk ¶
AdaptStreamChunk transforms a single SSE data payload from the target provider format to the source (caller) format via the canonical model.
If the two formats are wire-compatible the chunk is returned unmodified, except when provider-specific extensions require canonical filtering.
Returns (nil, nil) when the chunk should be skipped (e.g. Anthropic ping).
func (*Registry) DecodeRequestFor ¶
func (r *Registry) DecodeRequestFor(body []byte, providerFormat Format) (*CanonicalRequest, error)
DecodeRequestFor decodes a raw provider request into the canonical model.
func (*Registry) DecodeResponseFor ¶
func (r *Registry) DecodeResponseFor(body []byte, providerFormat Format) (*CanonicalResponse, error)
DecodeResponseFor decodes a raw provider response into the canonical model.
func (*Registry) DecodeStreamChunkFor ¶
func (r *Registry) DecodeStreamChunkFor(chunk []byte, target Format) (*CanonicalStreamChunk, error)
DecodeStreamChunkFor decodes a single SSE data payload from the given provider format into a canonical stream chunk.
func (*Registry) EncodeStreamChunkFor ¶
func (r *Registry) EncodeStreamChunkFor(canonical *CanonicalStreamChunk, source Format) ([][]byte, error)
EncodeStreamChunkFor encodes a canonical stream chunk into the given provider's SSE format.
func (*Registry) GetAdapter ¶
func (r *Registry) GetAdapter(f Format) (ProviderAdapter, error)
GetAdapter returns the adapter for a format, resolving aliases.
func (*Registry) Register ¶
func (r *Registry) Register(f Format, a ProviderAdapter)
Register adds or replaces an adapter for the given format.
type RequestAdapter ¶
type RequestAdapter interface {
DecodeRequest(body []byte) (*CanonicalRequest, error)
EncodeRequest(req *CanonicalRequest) ([]byte, error)
}
RequestAdapter converts between a provider's native request format and the canonical internal model.
type RequestDecodeError ¶
RequestDecodeError signals that the incoming request body could not be parsed into the expected provider format. The handler should surface this as an HTTP 400 instead of a 502.
func (*RequestDecodeError) Error ¶
func (e *RequestDecodeError) Error() string
func (*RequestDecodeError) Unwrap ¶
func (e *RequestDecodeError) Unwrap() error
type ResponseAdapter ¶
type ResponseAdapter interface {
DecodeResponse(body []byte) (*CanonicalResponse, error)
EncodeResponse(resp *CanonicalResponse) ([]byte, error)
}
ResponseAdapter converts between a provider's native response format and the canonical internal model.
type StreamAdapter ¶
type StreamAdapter interface {
DecodeStreamChunk(chunk []byte) (*CanonicalStreamChunk, error)
EncodeStreamChunk(chunk *CanonicalStreamChunk) ([][]byte, error)
}
StreamAdapter converts between a provider's native SSE chunk format and the canonical internal model.
EncodeStreamChunk returns a slice of raw SSE lines. Each element is written followed by "\n" by the handler. Typical elements include "event: …", "data: {…}" and "" (empty-line event separator). This allows providers that require multi-line SSE events (e.g. Anthropic's event: + data:) to produce a byte-accurate stream.
type StreamToolCallDelta ¶
type StreamToolCallDelta struct {
Index int `json:"index"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
ArgumentsDelta string `json:"arguments_delta,omitempty"` // incremental piece
}
StreamToolCallDelta is one tool-call delta in a streamed response (OpenAI streams tool_calls with incremental arguments; Anthropic uses input_json_delta).
Source Files
¶
- anthropic_adapter.go
- bedrock_adapter.go
- canonical.go
- cohere_adapter.go
- cohere_embed_adapter.go
- cohere_rerank_adapter.go
- format.go
- gemini_adapter.go
- helpers.go
- mistral_adapter.go
- model.go
- normalize.go
- openai_adapter.go
- openai_completions_adapter.go
- openai_responses_adapter.go
- openrouter_adapter.go
- provider_error.go
- registry.go
- stream.go