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