-
Notifications
You must be signed in to change notification settings - Fork 0
/
anthropic.go
138 lines (114 loc) · 3.51 KB
/
anthropic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Package anthropic provides a client library for interacting with the
// Anthropic safety-first language model REST APIs.
package anthropic
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"net/http"
"net/url"
)
const (
defaultAPIVersion = "2023-06-01"
defaultBaseURL = "https://api.anthropic.com/v1/"
defaultBaseUserAgent = "anthropic-sdk-go"
)
// Client manages communication with the Anthropic REST API.
type Client struct {
baseURL *url.URL
httpClient *http.Client
reusable service
Messages *MessagesService
}
type service struct{ client *Client }
// NewClient returns a new Anthropic REST API client. If a nil httpClient is
// provided, a new http.Client will be used.
// Adapted from go-github's NewClient method:
// https://github.com/google/go-github/blob/master/github/github.go
func NewClient(httpClient *http.Client) *Client {
if httpClient == nil {
httpClient = &http.Client{}
}
claude := &Client{httpClient: httpClient}
claude.baseURL, _ = url.Parse(defaultBaseURL)
claude.reusable.client = claude
claude.Messages = (*MessagesService)(&claude.reusable)
return claude
}
// NewRequest creates an API request. A relative URL can be provided in path,
// in which case it is resolved relative to the BaseURL of the Client.
// Paths should always be specified without a preceding slash.
// If specified, the value pointed to by body is JSON encoded and included as
// the request body.
// Adapted from go-github's Client.NewRequest method:
// https://github.com/google/go-github/blob/master/github/github.go
func (c *Client) NewRequest(method, path string, body any) (*http.Request, error) {
u, err := c.baseURL.Parse(path)
if err != nil {
return nil, err
}
var buf io.ReadWriter
if body != nil {
buf = &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err = enc.Encode(body)
if err != nil {
return nil, err
}
}
req, err := http.NewRequest(method, u.String(), buf)
if err != nil {
return nil, err
}
req.Header.Set("anthropic-version", defaultAPIVersion)
req.Header.Set("user-agent", defaultBaseUserAgent+"/"+semanticVersion)
if body != nil {
req.Header.Set("content-type", "application/json")
}
return req, nil
}
// Do sends an API request and returns the API response. The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an error
// if an API error has occurred. If v implements the io.Writer interface, the
// raw response body will be written to v without attempting to first decode it.
// If v is nil, and no error occurs, the response is returned as-is.
// Adapted from go-github's Client.BareDo and Client.Do methods:
// https://github.com/google/go-github/blob/master/github/github.go
func (c *Client) Do(ctx context.Context, req *http.Request, v any) (*http.Response, error) {
if ctx == nil {
return nil, errors.New("context must be non-nil")
}
req = req.WithContext(ctx)
resp, err := c.httpClient.Do(req)
if err != nil {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
return nil, err
}
//goland:noinspection GoUnhandledErrorResult
defer resp.Body.Close()
switch v := v.(type) {
case nil:
case io.Writer:
_, err = io.Copy(v, resp.Body)
default:
decErr := json.NewDecoder(resp.Body).Decode(v)
if decErr == io.EOF {
decErr = nil
}
if decErr != nil {
err = decErr
}
}
return resp, err
}
// Float64 returns a pointer to a float64 value.
func Float64(v float64) *float64 { return &v }
// Int returns a pointer to an int value.
func Int(v int) *int { return &v }