1// Package vercel provides an implementation of the fantasy AI SDK for Vercel AI Gateway.
2package vercel
3
4import (
5 "charm.land/fantasy"
6 "charm.land/fantasy/providers/openai"
7 "github.com/openai/openai-go/v2/option"
8)
9
10type options struct {
11 openaiOptions []openai.Option
12 languageModelOptions []openai.LanguageModelOption
13 sdkOptions []option.RequestOption
14 objectMode fantasy.ObjectMode
15}
16
17const (
18 // DefaultURL is the default URL for the Vercel AI Gateway API.
19 DefaultURL = "https://ai-gateway.vercel.sh/v1"
20 // Name is the name of the Vercel provider.
21 Name = "vercel"
22)
23
24// Option defines a function that configures Vercel provider options.
25type Option = func(*options)
26
27// New creates a new Vercel AI Gateway provider with the given options.
28func New(opts ...Option) (fantasy.Provider, error) {
29 providerOptions := options{
30 openaiOptions: []openai.Option{
31 openai.WithName(Name),
32 openai.WithBaseURL(DefaultURL),
33 },
34 languageModelOptions: []openai.LanguageModelOption{
35 openai.WithLanguageModelPrepareCallFunc(languagePrepareModelCall),
36 openai.WithLanguageModelUsageFunc(languageModelUsage),
37 openai.WithLanguageModelStreamUsageFunc(languageModelStreamUsage),
38 openai.WithLanguageModelStreamExtraFunc(languageModelStreamExtra),
39 openai.WithLanguageModelExtraContentFunc(languageModelExtraContent),
40 openai.WithLanguageModelToPromptFunc(languageModelToPrompt),
41 },
42 objectMode: fantasy.ObjectModeTool, // Default to tool mode for vercel
43 }
44 for _, o := range opts {
45 o(&providerOptions)
46 }
47
48 // Handle object mode: convert unsupported modes to tool
49 // Vercel AI Gateway doesn't support native JSON mode, so we use tool or text
50 objectMode := providerOptions.objectMode
51 if objectMode == fantasy.ObjectModeAuto || objectMode == fantasy.ObjectModeJSON {
52 objectMode = fantasy.ObjectModeTool
53 }
54
55 providerOptions.openaiOptions = append(
56 providerOptions.openaiOptions,
57 openai.WithSDKOptions(providerOptions.sdkOptions...),
58 openai.WithLanguageModelOptions(providerOptions.languageModelOptions...),
59 openai.WithObjectMode(objectMode),
60 )
61 return openai.New(providerOptions.openaiOptions...)
62}
63
64// WithAPIKey sets the API key for the Vercel provider.
65func WithAPIKey(apiKey string) Option {
66 return func(o *options) {
67 o.openaiOptions = append(o.openaiOptions, openai.WithAPIKey(apiKey))
68 }
69}
70
71// WithBaseURL sets the base URL for the Vercel provider.
72func WithBaseURL(url string) Option {
73 return func(o *options) {
74 o.openaiOptions = append(o.openaiOptions, openai.WithBaseURL(url))
75 }
76}
77
78// WithName sets the name for the Vercel provider.
79func WithName(name string) Option {
80 return func(o *options) {
81 o.openaiOptions = append(o.openaiOptions, openai.WithName(name))
82 }
83}
84
85// WithHeaders sets the headers for the Vercel provider.
86func WithHeaders(headers map[string]string) Option {
87 return func(o *options) {
88 o.openaiOptions = append(o.openaiOptions, openai.WithHeaders(headers))
89 }
90}
91
92// WithHTTPClient sets the HTTP client for the Vercel provider.
93func WithHTTPClient(client option.HTTPClient) Option {
94 return func(o *options) {
95 o.openaiOptions = append(o.openaiOptions, openai.WithHTTPClient(client))
96 }
97}
98
99// WithSDKOptions sets the SDK options for the Vercel provider.
100func WithSDKOptions(opts ...option.RequestOption) Option {
101 return func(o *options) {
102 o.sdkOptions = append(o.sdkOptions, opts...)
103 }
104}
105
106// WithObjectMode sets the object generation mode for the Vercel provider.
107// Supported modes: ObjectModeTool, ObjectModeText.
108// ObjectModeAuto and ObjectModeJSON are automatically converted to ObjectModeTool
109// since Vercel AI Gateway doesn't support native JSON mode.
110func WithObjectMode(om fantasy.ObjectMode) Option {
111 return func(o *options) {
112 o.objectMode = om
113 }
114}