provider_options.go

  1// Package openrouter provides an implementation of the fantasy AI SDK for OpenRouter's language models.
  2package openrouter
  3
  4import (
  5	"encoding/json"
  6
  7	"charm.land/fantasy"
  8)
  9
 10// ReasoningEffort represents the reasoning effort level for OpenRouter models.
 11type ReasoningEffort string
 12
 13const (
 14	// ReasoningEffortNone represents ReasoningEffortNone reasoning effort.
 15	ReasoningEffortNone ReasoningEffort = "none"
 16	// ReasoningEffortMinimal represents minimal reasoning effort.
 17	ReasoningEffortMinimal ReasoningEffort = "minimal"
 18	// ReasoningEffortLow represents low reasoning effort.
 19	ReasoningEffortLow ReasoningEffort = "low"
 20	// ReasoningEffortMedium represents medium reasoning effort.
 21	ReasoningEffortMedium ReasoningEffort = "medium"
 22	// ReasoningEffortHigh represents high reasoning effort.
 23	ReasoningEffortHigh ReasoningEffort = "high"
 24	// ReasoningEffortXHigh represents extra high reasoning effort.
 25	ReasoningEffortXHigh ReasoningEffort = "xhigh"
 26)
 27
 28// Global type identifiers for OpenRouter-specific provider data.
 29const (
 30	TypeProviderOptions  = Name + ".options"
 31	TypeProviderMetadata = Name + ".metadata"
 32)
 33
 34// Register OpenRouter provider-specific types with the global registry.
 35func init() {
 36	fantasy.RegisterProviderType(TypeProviderOptions, func(data []byte) (fantasy.ProviderOptionsData, error) {
 37		var v ProviderOptions
 38		if err := json.Unmarshal(data, &v); err != nil {
 39			return nil, err
 40		}
 41		return &v, nil
 42	})
 43	fantasy.RegisterProviderType(TypeProviderMetadata, func(data []byte) (fantasy.ProviderOptionsData, error) {
 44		var v ProviderMetadata
 45		if err := json.Unmarshal(data, &v); err != nil {
 46			return nil, err
 47		}
 48		return &v, nil
 49	})
 50}
 51
 52// PromptTokensDetails represents details about prompt tokens for OpenRouter.
 53type PromptTokensDetails struct {
 54	CachedTokens int64 `json:"cached_tokens"`
 55}
 56
 57// CompletionTokensDetails represents details about completion tokens for OpenRouter.
 58type CompletionTokensDetails struct {
 59	ReasoningTokens int64 `json:"reasoning_tokens"`
 60}
 61
 62// CostDetails represents cost details for OpenRouter.
 63type CostDetails struct {
 64	UpstreamInferenceCost            float64 `json:"upstream_inference_cost"`
 65	UpstreamInferencePromptCost      float64 `json:"upstream_inference_prompt_cost"`
 66	UpstreamInferenceCompletionsCost float64 `json:"upstream_inference_completions_cost"`
 67}
 68
 69// UsageAccounting represents usage accounting details for OpenRouter.
 70type UsageAccounting struct {
 71	PromptTokens            int64                   `json:"prompt_tokens"`
 72	PromptTokensDetails     PromptTokensDetails     `json:"prompt_tokens_details"`
 73	CompletionTokens        int64                   `json:"completion_tokens"`
 74	CompletionTokensDetails CompletionTokensDetails `json:"completion_tokens_details"`
 75	TotalTokens             int64                   `json:"total_tokens"`
 76	Cost                    float64                 `json:"cost"`
 77	CostDetails             CostDetails             `json:"cost_details"`
 78}
 79
 80// ProviderMetadata represents metadata from OpenRouter provider.
 81type ProviderMetadata struct {
 82	Provider string          `json:"provider"`
 83	Usage    UsageAccounting `json:"usage"`
 84}
 85
 86// Options implements the ProviderOptionsData interface for ProviderMetadata.
 87func (*ProviderMetadata) Options() {}
 88
 89// MarshalJSON implements custom JSON marshaling with type info for ProviderMetadata.
 90func (m ProviderMetadata) MarshalJSON() ([]byte, error) {
 91	type plain ProviderMetadata
 92	return fantasy.MarshalProviderType(TypeProviderMetadata, plain(m))
 93}
 94
 95// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderMetadata.
 96func (m *ProviderMetadata) UnmarshalJSON(data []byte) error {
 97	type plain ProviderMetadata
 98	var p plain
 99	if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
100		return err
101	}
102	*m = ProviderMetadata(p)
103	return nil
104}
105
106// ReasoningOptions represents reasoning options for OpenRouter.
107type ReasoningOptions struct {
108	// Whether reasoning is enabled
109	Enabled *bool `json:"enabled,omitempty"`
110	// Whether to exclude reasoning from the response
111	Exclude *bool `json:"exclude,omitempty"`
112	// Maximum number of tokens to use for reasoning
113	MaxTokens *int64 `json:"max_tokens,omitempty"`
114	// Reasoning effort level: "low" | "medium" | "high"
115	Effort *ReasoningEffort `json:"effort,omitempty"`
116}
117
118// Provider represents provider routing preferences for OpenRouter.
119type Provider struct {
120	// List of provider slugs to try in order (e.g. ["anthropic", "openai"])
121	Order []string `json:"order,omitempty"`
122	// Whether to allow backup providers when primary is unavailable (default: true)
123	AllowFallbacks *bool `json:"allow_fallbacks,omitempty"`
124	// Only use providers that support all parameters in your request (default: false)
125	RequireParameters *bool `json:"require_parameters,omitempty"`
126	// Control whether to use providers that may store data: "allow" | "deny"
127	DataCollection *string `json:"data_collection,omitempty"`
128	// List of provider slugs to allow for this request
129	Only []string `json:"only,omitempty"`
130	// List of provider slugs to skip for this request
131	Ignore []string `json:"ignore,omitempty"`
132	// List of quantization levels to filter by (e.g. ["int4", "int8"])
133	Quantizations []string `json:"quantizations,omitempty"`
134	// Sort providers by "price" | "throughput" | "latency"
135	Sort *string `json:"sort,omitempty"`
136}
137
138// ProviderOptions represents additional options for OpenRouter provider.
139type ProviderOptions struct {
140	Reasoning    *ReasoningOptions `json:"reasoning,omitempty"`
141	ExtraBody    map[string]any    `json:"extra_body,omitempty"`
142	IncludeUsage *bool             `json:"include_usage,omitempty"`
143	// Modify the likelihood of specified tokens appearing in the completion.
144	// Accepts a map that maps tokens (specified by their token ID) to an associated bias value from -100 to 100.
145	// The bias is added to the logits generated by the model prior to sampling.
146	LogitBias map[string]int64 `json:"logit_bias,omitempty"`
147	// Return the log probabilities of the tokens. Including logprobs will increase the response size.
148	// Setting to true will return the log probabilities of the tokens that were generated.
149	LogProbs *bool `json:"log_probs,omitempty"`
150	// Whether to enable parallel function calling during tool use. Default to true.
151	ParallelToolCalls *bool `json:"parallel_tool_calls,omitempty"`
152	// A unique identifier representing your end-user, which can help OpenRouter to monitor and detect abuse.
153	User *string `json:"user,omitempty"`
154	// Provider routing preferences to control request routing behavior
155	Provider *Provider `json:"provider,omitempty"`
156	// TODO: add the web search plugin config
157}
158
159// Options implements the ProviderOptionsData interface for ProviderOptions.
160func (*ProviderOptions) Options() {}
161
162// MarshalJSON implements custom JSON marshaling with type info for ProviderOptions.
163func (o ProviderOptions) MarshalJSON() ([]byte, error) {
164	type plain ProviderOptions
165	return fantasy.MarshalProviderType(TypeProviderOptions, plain(o))
166}
167
168// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderOptions.
169func (o *ProviderOptions) UnmarshalJSON(data []byte) error {
170	type plain ProviderOptions
171	var p plain
172	if err := fantasy.UnmarshalProviderType(data, &p); err != nil {
173		return err
174	}
175	*o = ProviderOptions(p)
176	return nil
177}
178
179// ReasoningDetail represents a reasoning detail for OpenRouter.
180type ReasoningDetail struct {
181	ID        string `json:"id,omitempty"`
182	Type      string `json:"type,omitempty"`
183	Text      string `json:"text,omitempty"`
184	Data      string `json:"data,omitempty"`
185	Format    string `json:"format,omitempty"`
186	Summary   string `json:"summary,omitempty"`
187	Signature string `json:"signature,omitempty"`
188	Index     int    `json:"index"`
189}
190
191// ReasoningData represents reasoning data for OpenRouter.
192type ReasoningData struct {
193	Reasoning        string            `json:"reasoning"`
194	ReasoningDetails []ReasoningDetail `json:"reasoning_details"`
195}
196
197// ReasoningEffortOption creates a pointer to a ReasoningEffort value for OpenRouter.
198//
199//go:fix inline
200func ReasoningEffortOption(e ReasoningEffort) *ReasoningEffort {
201	return new(e)
202}
203
204// NewProviderOptions creates new provider options for OpenRouter.
205func NewProviderOptions(opts *ProviderOptions) fantasy.ProviderOptions {
206	return fantasy.ProviderOptions{
207		Name: opts,
208	}
209}
210
211// ParseOptions parses provider options from a map for OpenRouter.
212func ParseOptions(data map[string]any) (*ProviderOptions, error) {
213	var options ProviderOptions
214	if err := fantasy.ParseOptions(data, &options); err != nil {
215		return nil, err
216	}
217	return &options, nil
218}