1package openrouter
2
3import (
4 "encoding/json"
5
6 "github.com/charmbracelet/fantasy/ai"
7 "github.com/charmbracelet/fantasy/openai"
8 "github.com/openai/openai-go/v2/option"
9)
10
11type options struct {
12 openaiOptions []openai.Option
13}
14
15const (
16 DefaultURL = "https://openrouter.ai/api/v1"
17)
18
19type Option = func(*options)
20
21func New(opts ...Option) ai.Provider {
22 providerOptions := options{
23 openaiOptions: []openai.Option{
24 openai.WithBaseURL(DefaultURL),
25 openai.WithLanguageModelOptions(
26 openai.WithPrepareLanguageModelCallFunc(prepareLanguageModelCall),
27 ),
28 },
29 }
30 for _, o := range opts {
31 o(&providerOptions)
32 }
33 return openai.New(providerOptions.openaiOptions...)
34}
35
36func WithAPIKey(apiKey string) Option {
37 return func(o *options) {
38 o.openaiOptions = append(o.openaiOptions, openai.WithAPIKey(apiKey))
39 }
40}
41
42func WithName(name string) Option {
43 return func(o *options) {
44 o.openaiOptions = append(o.openaiOptions, openai.WithName(name))
45 }
46}
47
48func WithHeaders(headers map[string]string) Option {
49 return func(o *options) {
50 o.openaiOptions = append(o.openaiOptions, openai.WithHeaders(headers))
51 }
52}
53
54func WithHTTPClient(client option.HTTPClient) Option {
55 return func(o *options) {
56 o.openaiOptions = append(o.openaiOptions, openai.WithHTTPClient(client))
57 }
58}
59
60func structToMapJSON(s any) (map[string]any, error) {
61 var result map[string]any
62 jsonBytes, err := json.Marshal(s)
63 if err != nil {
64 return nil, err
65 }
66 err = json.Unmarshal(jsonBytes, &result)
67 if err != nil {
68 return nil, err
69 }
70 return result, nil
71}