1// Package openrouter provides an implementation of the fantasy AI SDK for OpenRouter's language models.
2package openrouter
3
4import (
5 "charm.land/fantasy"
6)
7
8// ReasoningEffort represents the reasoning effort level for OpenRouter models.
9type ReasoningEffort string
10
11const (
12 // ReasoningEffortLow represents low reasoning effort.
13 ReasoningEffortLow ReasoningEffort = "low"
14 // ReasoningEffortMedium represents medium reasoning effort.
15 ReasoningEffortMedium ReasoningEffort = "medium"
16 // ReasoningEffortHigh represents high reasoning effort.
17 ReasoningEffortHigh ReasoningEffort = "high"
18)
19
20// PromptTokensDetails represents details about prompt tokens for OpenRouter.
21type PromptTokensDetails struct {
22 CachedTokens int64
23}
24
25// CompletionTokensDetails represents details about completion tokens for OpenRouter.
26type CompletionTokensDetails struct {
27 ReasoningTokens int64
28}
29
30// CostDetails represents cost details for OpenRouter.
31type CostDetails struct {
32 UpstreamInferenceCost float64 `json:"upstream_inference_cost"`
33 UpstreamInferencePromptCost float64 `json:"upstream_inference_prompt_cost"`
34 UpstreamInferenceCompletionsCost float64 `json:"upstream_inference_completions_cost"`
35}
36
37// UsageAccounting represents usage accounting details for OpenRouter.
38type UsageAccounting struct {
39 PromptTokens int64 `json:"prompt_tokens"`
40 PromptTokensDetails PromptTokensDetails `json:"prompt_tokens_details"`
41 CompletionTokens int64 `json:"completion_tokens"`
42 CompletionTokensDetails CompletionTokensDetails `json:"completion_tokens_details"`
43 TotalTokens int64 `json:"total_tokens"`
44 Cost float64 `json:"cost"`
45 CostDetails CostDetails `json:"cost_details"`
46}
47
48// ProviderMetadata represents metadata from OpenRouter provider.
49type ProviderMetadata struct {
50 Provider string `json:"provider"`
51 Usage UsageAccounting `json:"usage"`
52}
53
54// Options implements the ProviderOptionsData interface for ProviderMetadata.
55func (*ProviderMetadata) Options() {}
56
57// ReasoningOptions represents reasoning options for OpenRouter.
58type ReasoningOptions struct {
59 // Whether reasoning is enabled
60 Enabled *bool `json:"enabled,omitempty"`
61 // Whether to exclude reasoning from the response
62 Exclude *bool `json:"exclude,omitempty"`
63 // Maximum number of tokens to use for reasoning
64 MaxTokens *int64 `json:"max_tokens,omitempty"`
65 // Reasoning effort level: "low" | "medium" | "high"
66 Effort *ReasoningEffort `json:"effort,omitempty"`
67}
68
69// Provider represents provider routing preferences for OpenRouter.
70type Provider struct {
71 // List of provider slugs to try in order (e.g. ["anthropic", "openai"])
72 Order []string `json:"order,omitempty"`
73 // Whether to allow backup providers when primary is unavailable (default: true)
74 AllowFallbacks *bool `json:"allow_fallbacks,omitempty"`
75 // Only use providers that support all parameters in your request (default: false)
76 RequireParameters *bool `json:"require_parameters,omitempty"`
77 // Control whether to use providers that may store data: "allow" | "deny"
78 DataCollection *string `json:"data_collection,omitempty"`
79 // List of provider slugs to allow for this request
80 Only []string `json:"only,omitempty"`
81 // List of provider slugs to skip for this request
82 Ignore []string `json:"ignore,omitempty"`
83 // List of quantization levels to filter by (e.g. ["int4", "int8"])
84 Quantizations []string `json:"quantizations,omitempty"`
85 // Sort providers by "price" | "throughput" | "latency"
86 Sort *string `json:"sort,omitempty"`
87}
88
89// ProviderOptions represents additional options for OpenRouter provider.
90type ProviderOptions struct {
91 Reasoning *ReasoningOptions `json:"reasoning,omitempty"`
92 ExtraBody map[string]any `json:"extra_body,omitempty"`
93 IncludeUsage *bool `json:"include_usage,omitempty"`
94 // Modify the likelihood of specified tokens appearing in the completion.
95 // Accepts a map that maps tokens (specified by their token ID) to an associated bias value from -100 to 100.
96 // The bias is added to the logits generated by the model prior to sampling.
97 LogitBias map[string]int64 `json:"logit_bias,omitempty"`
98 // Return the log probabilities of the tokens. Including logprobs will increase the response size.
99 // Setting to true will return the log probabilities of the tokens that were generated.
100 LogProbs *bool `json:"log_probs,omitempty"`
101 // Whether to enable parallel function calling during tool use. Default to true.
102 ParallelToolCalls *bool `json:"parallel_tool_calls,omitempty"`
103 // A unique identifier representing your end-user, which can help OpenRouter to monitor and detect abuse.
104 User *string `json:"user,omitempty"`
105 // Provider routing preferences to control request routing behavior
106 Provider *Provider `json:"provider,omitempty"`
107 // TODO: add the web search plugin config
108}
109
110// Options implements the ProviderOptionsData interface for ProviderOptions.
111func (*ProviderOptions) Options() {}
112
113// ReasoningDetail represents a reasoning detail for OpenRouter.
114type ReasoningDetail struct {
115 ID string `json:"id,omitempty"`
116 Type string `json:"type,omitempty"`
117 Text string `json:"text,omitempty"`
118 Data string `json:"data,omitempty"`
119 Format string `json:"format,omitempty"`
120 Summary string `json:"summary,omitempty"`
121 Signature string `json:"signature,omitempty"`
122 Index int `json:"index"`
123}
124
125// ReasoningData represents reasoning data for OpenRouter.
126type ReasoningData struct {
127 Reasoning string `json:"reasoning"`
128 ReasoningDetails []ReasoningDetail `json:"reasoning_details"`
129}
130
131// ReasoningEffortOption creates a pointer to a ReasoningEffort value for OpenRouter.
132func ReasoningEffortOption(e ReasoningEffort) *ReasoningEffort {
133 return &e
134}
135
136// NewProviderOptions creates new provider options for OpenRouter.
137func NewProviderOptions(opts *ProviderOptions) fantasy.ProviderOptions {
138 return fantasy.ProviderOptions{
139 Name: opts,
140 }
141}
142
143// ParseOptions parses provider options from a map for OpenRouter.
144func ParseOptions(data map[string]any) (*ProviderOptions, error) {
145 var options ProviderOptions
146 if err := fantasy.ParseOptions(data, &options); err != nil {
147 return nil, err
148 }
149 return &options, nil
150}