on main help sign in
chore: update vendor dependencies
11959dcAyman Bagabas
vendor/github.com/charmbracelet/bubbletea/v2/tea.go+4−11
@@ -83,13 +83,6 @@ type ViewableModel interface {
83 View() View
83 View() View
84}
84}
85
85
86−// StyledString returns a [Layer] that can be styled with ANSI escape
87−// codes. It is used to render text with different colors, styles, and other
88−// attributes on the terminal screen.
89−func StyledString(s string) *uv.StyledString {
90− return uv.NewStyledString(s)
91−}
92−
93// Buffer represents a terminal cell buffer that defines the current state of
86// Buffer represents a terminal cell buffer that defines the current state of
94// the terminal screen.
87// the terminal screen.
95type Buffer = uv.Buffer
88type Buffer = uv.Buffer
@@ -127,13 +120,13 @@ func NewView(s any) View {
127 var view View
120 var view View
128 switch v := s.(type) {
121 switch v := s.(type) {
129 case string:
122 case string:
130− view.Layer = StyledString(v)
123+ view.Layer = uv.NewStyledString(v)
131 case fmt.Stringer:
124 case fmt.Stringer:
132− view.Layer = StyledString(v.String())
125+ view.Layer = uv.NewStyledString(v.String())
133 case Layer:
126 case Layer:
134 view.Layer = v
127 view.Layer = v
135 default:
128 default:
136− view.Layer = StyledString(fmt.Sprintf("%v", v))
129+ view.Layer = uv.NewStyledString(fmt.Sprintf("%v", v))
137 }
130 }
138 return view
131 return view
139}
132}
@@ -867,7 +860,7 @@ func (p *Program) render(model Model) {
867 case CursorModel:
860 case CursorModel:
868 frame, view.Cursor = model.View()
861 frame, view.Cursor = model.View()
869 }
862 }
870− view.Layer = StyledString(frame)
863+ view.Layer = uv.NewStyledString(frame)
871 view.BackgroundColor = p.lastBgColor
864 view.BackgroundColor = p.lastBgColor
872 view.ForegroundColor = p.lastFgColor
865 view.ForegroundColor = p.lastFgColor
873 view.WindowTitle = p.lastWindowTitle
866 view.WindowTitle = p.lastWindowTitle
vendor/github.com/charmbracelet/lipgloss/v2/get.go+1
@@ -543,6 +543,7 @@ func (s Style) getAsTransform(propKey) func(string) string {
543// line.
543// line.
544func getLines(s string) (lines []string, widest int) {
544func getLines(s string) (lines []string, widest int) {
545 s = strings.ReplaceAll(s, "\t", " ")
545 s = strings.ReplaceAll(s, "\t", " ")
546+ s = strings.ReplaceAll(s, "\r\n", "\n")
546 lines = strings.Split(s, "\n")
547 lines = strings.Split(s, "\n")
547
548
548 for _, l := range lines {
549 for _, l := range lines {
vendor/github.com/charmbracelet/ultraviolet/LICENSEnew file+5
@@ -0,0 +1,5 @@
1+Copyright © 2025 Charmbracelet, Inc.
2+
3+This project is currently in development and is not yet licensed for public use.
4+
5+All rights reserved. No license is granted at this time.
vendor/github.com/charmbracelet/ultraviolet/README.md+5−11
@@ -9,18 +9,12 @@
9> [!CAUTION]
9> [!CAUTION]
10> This project is in very early development and may change significantly at any moment. Expect no API guarantees as of now.
10> This project is in very early development and may change significantly at any moment. Expect no API guarantees as of now.
11
11
12−Ultraviolet is a Go library for building text-based applications with a focus
12+Ultraviolet is a set of of primitives for manipulating terminal emulators with
13−on terminal user interfaces (TUIs). It provides a set of tools and abstractions
13+a focus on terminal user interfaces (TUIs). It provides a set of tools and
14−to create interactive terminal applications that can handle user input and
14+abstractions for interactive terminal applications that can handle user input
15−display dynamic content in a cell-based manner.
15+and display dynamic, cell-based content.
16
16
17−## Installation
18−
19−To install UV, you can simply run in your Go project:
20−
21−```bash
22−go get github.com/charmbracelet/ultraviolet
17+[Ultraviolet is not yet licensed.](https://github.com/charmbracelet/ultraviolet/raw/main/LICENSE)
23−```
24
18
25---
19---
26
20
vendor/github.com/charmbracelet/ultraviolet/terminal_renderer.go+26−26
@@ -378,7 +378,10 @@ func (s *TerminalRenderer) moveCursor(newbuf *Buffer, x, y int, overwrite bool)
378 s.buf.WriteByte('\r') //nolint:errcheck
378 s.buf.WriteByte('\r') //nolint:errcheck
379 s.cur.X, s.cur.Y = 0, 0
379 s.cur.X, s.cur.Y = 0, 0
380 }
380 }
381− s.buf.WriteString(moveCursor(s, newbuf, x, y, overwrite)) //nolint:errcheck
381+ seq, scrollHeight := moveCursor(s, newbuf, x, y, overwrite)
382+ // If we scrolled the screen, we need to update the scroll height.
383+ s.scrollHeight = max(s.scrollHeight, scrollHeight)
384+ s.buf.WriteString(seq) //nolint:errcheck
382 s.cur.X, s.cur.Y = x, y
385 s.cur.X, s.cur.Y = x, y
383}
386}
384
387
@@ -1316,13 +1319,11 @@ func notLocal(cols, fx, fy, tx, ty int) bool {
1316//
1319//
1317// It is safe to call this function with a nil [Buffer]. In that case, it won't
1320// It is safe to call this function with a nil [Buffer]. In that case, it won't
1318// use any optimizations that require the new buffer such as overwrite.
1321// use any optimizations that require the new buffer such as overwrite.
1319−func relativeCursorMove(s *TerminalRenderer, newbuf *Buffer, fx, fy, tx, ty int, overwrite, useTabs, useBackspace bool) string {
1322+func relativeCursorMove(s *TerminalRenderer, newbuf *Buffer, fx, fy, tx, ty int, overwrite, useTabs, useBackspace bool) (string, int) {
1320 var seq strings.Builder
1323 var seq strings.Builder
1321− height := -1
1324+ var scrollHeight int
1322 if newbuf == nil {
1325 if newbuf == nil {
1323 overwrite = false // We can't overwrite the current buffer.
1326 overwrite = false // We can't overwrite the current buffer.
1324− } else {
1325− height = newbuf.Height()
1326 }
1327 }
1327
1328
1328 if ty != fy {
1329 if ty != fy {
@@ -1331,21 +1332,15 @@ func relativeCursorMove(s *TerminalRenderer, newbuf *Buffer, fx, fy, tx, ty int,
1331 yseq = ansi.VerticalPositionAbsolute(ty + 1)
1332 yseq = ansi.VerticalPositionAbsolute(ty + 1)
1332 }
1333 }
1333
1334
1334− // OPTIM: Use [ansi.LF] and [ansi.ReverseIndex] as optimizations.
1335−
1336 if ty > fy {
1335 if ty > fy {
1337 n := ty - fy
1336 n := ty - fy
1338 if cud := ansi.CursorDown(n); yseq == "" || len(cud) < len(yseq) {
1337 if cud := ansi.CursorDown(n); yseq == "" || len(cud) < len(yseq) {
1339 yseq = cud
1338 yseq = cud
1340 }
1339 }
1341 shouldScroll := !s.flags.Contains(tAltScreen) && ty > s.scrollHeight
1340 shouldScroll := !s.flags.Contains(tAltScreen) && ty > s.scrollHeight
1342− if shouldScroll && ty == s.scrollHeight && ty < height {
1343− n = min(n, height-1-ty)
1344− }
1345− if lf := strings.Repeat("\n", n); shouldScroll ||
1341+ if lf := strings.Repeat("\n", n); shouldScroll || len(lf) < len(yseq) {
1346− ((ty < height || height == -1) && len(lf) < len(yseq)) {
1347 yseq = lf
1342 yseq = lf
1348− s.scrollHeight = max(s.scrollHeight, ty)
1343+ scrollHeight = ty
1349 if s.flags.Contains(tMapNewline) {
1344 if s.flags.Contains(tMapNewline) {
1350 fx = 0
1345 fx = 0
1351 }
1346 }
@@ -1468,7 +1463,7 @@ func relativeCursorMove(s *TerminalRenderer, newbuf *Buffer, fx, fy, tx, ty int,
1468 seq.WriteString(xseq)
1463 seq.WriteString(xseq)
1469 }
1464 }
1470
1465
1471− return seq.String()
1466+ return seq.String(), scrollHeight
1472}
1467}
1473
1468
1474// moveCursor moves and returns the cursor movement sequence to move the cursor
1469// moveCursor moves and returns the cursor movement sequence to move the cursor
@@ -1478,7 +1473,7 @@ func relativeCursorMove(s *TerminalRenderer, newbuf *Buffer, fx, fy, tx, ty int,
1478//
1473//
1479// It is safe to call this function with a nil [Buffer]. In that case, it won't
1474// It is safe to call this function with a nil [Buffer]. In that case, it won't
1480// use any optimizations that require the new buffer such as overwrite.
1475// use any optimizations that require the new buffer such as overwrite.
1481−func moveCursor(s *TerminalRenderer, newbuf *Buffer, x, y int, overwrite bool) (seq string) {
1476+func moveCursor(s *TerminalRenderer, newbuf *Buffer, x, y int, overwrite bool) (seq string, scrollHeight int) {
1482 fx, fy := s.cur.X, s.cur.Y
1477 fx, fy := s.cur.X, s.cur.Y
1483
1478
1484 if !s.flags.Contains(tRelativeCursor) {
1479 if !s.flags.Contains(tRelativeCursor) {
@@ -1496,7 +1491,7 @@ func moveCursor(s *TerminalRenderer, newbuf *Buffer, x, y int, overwrite bool) (
1496 // Method #0: Use [ansi.CUP] if the distance is long.
1491 // Method #0: Use [ansi.CUP] if the distance is long.
1497 seq = ansi.CursorPosition(x+1, y+1)
1492 seq = ansi.CursorPosition(x+1, y+1)
1498 if fx == -1 || fy == -1 || width == -1 || notLocal(width, fx, fy, x, y) {
1493 if fx == -1 || fy == -1 || width == -1 || notLocal(width, fx, fy, x, y) {
1499− return
1494+ return seq, 0
1500 }
1495 }
1501 }
1496 }
1502
1497
@@ -1520,27 +1515,32 @@ func moveCursor(s *TerminalRenderer, newbuf *Buffer, x, y int, overwrite bool) (
1520 useBackspace := i&1 != 0
1515 useBackspace := i&1 != 0
1521
1516
1522 // Method #1: Use local movement sequences.
1517 // Method #1: Use local movement sequences.
1523− nseq := relativeCursorMove(s, newbuf, fx, fy, x, y, overwrite, useHardTabs, useBackspace)
1518+ nseq1, nscrollHeight1 := relativeCursorMove(s, newbuf, fx, fy, x, y, overwrite, useHardTabs, useBackspace)
1524− if (i == 0 && len(seq) == 0) || len(nseq) < len(seq) {
1519+ if (i == 0 && len(seq) == 0) || len(nseq1) < len(seq) {
1525− seq = nseq
1520+ seq = nseq1
1521+ scrollHeight = max(scrollHeight, nscrollHeight1)
1526 }
1522 }
1527
1523
1528 // Method #2: Use [ansi.CR] and local movement sequences.
1524 // Method #2: Use [ansi.CR] and local movement sequences.
1529− nseq = "\r" + relativeCursorMove(s, newbuf, 0, fy, x, y, overwrite, useHardTabs, useBackspace)
1525+ nseq2, nscrollHeight2 := relativeCursorMove(s, newbuf, 0, fy, x, y, overwrite, useHardTabs, useBackspace)
1526+ nseq2 = "\r" + nseq2
1530− if len(nseq) < len(seq) {
1527+ if len(nseq2) < len(seq) {
1531− seq = nseq
1528+ seq = nseq2
1529+ scrollHeight = max(scrollHeight, nscrollHeight2)
1532 }
1530 }
1533
1531
1534 if !s.flags.Contains(tRelativeCursor) {
1532 if !s.flags.Contains(tRelativeCursor) {
1535 // Method #3: Use [ansi.CursorHomePosition] and local movement sequences.
1533 // Method #3: Use [ansi.CursorHomePosition] and local movement sequences.
1536− nseq = ansi.CursorHomePosition + relativeCursorMove(s, newbuf, 0, 0, x, y, overwrite, useHardTabs, useBackspace)
1534+ nseq3, nscrollHeight3 := relativeCursorMove(s, newbuf, 0, 0, x, y, overwrite, useHardTabs, useBackspace)
1535+ nseq3 = ansi.CursorHomePosition + nseq3
1537− if len(nseq) < len(seq) {
1536+ if len(nseq3) < len(seq) {
1538− seq = nseq
1537+ seq = nseq3
1538+ scrollHeight = max(scrollHeight, nscrollHeight3)
1539 }
1539 }
1540 }
1540 }
1541 }
1541 }
1542
1542
1543− return
1543+ return seq, scrollHeight
1544}
1544}
1545
1545
1546// xtermCaps returns whether the terminal is xterm-like. This means that the
1546// xtermCaps returns whether the terminal is xterm-like. This means that the
vendor/github.com/charmbracelet/ultraviolet/terminal_renderer_hashmap.go+1−7
@@ -24,9 +24,6 @@ const newIndex = -1
24// updateHashmap updates the hashmap with the new hash value.
24// updateHashmap updates the hashmap with the new hash value.
25func (s *TerminalRenderer) updateHashmap(newbuf *Buffer) {
25func (s *TerminalRenderer) updateHashmap(newbuf *Buffer) {
26 height := newbuf.Height()
26 height := newbuf.Height()
27− if s.hashtab == nil || height >= len(s.hashtab) {
28− s.hashtab = make([]hashmap, (height+1)*2)
29− }
30
27
31 if len(s.oldhash) >= height && len(s.newhash) >= height {
28 if len(s.oldhash) >= height && len(s.newhash) >= height {
32 // rehash changed lines
29 // rehash changed lines
@@ -53,10 +50,7 @@ func (s *TerminalRenderer) updateHashmap(newbuf *Buffer) {
53 }
50 }
54 }
51 }
55
52
56− for i := 0; i < len(s.hashtab); i++ {
53+ s.hashtab = make([]hashmap, (height+1)*2)
57− s.hashtab[i] = hashmap{}
58− }
59−
60 for i := 0; i < height; i++ {
54 for i := 0; i < height; i++ {
61 hashval := s.oldhash[i]
55 hashval := s.oldhash[i]
62
56
vendor/github.com/charmbracelet/ultraviolet/tty.go+5
@@ -11,3 +11,8 @@ import "os"
11func OpenTTY() (inTty, outTty *os.File, err error) {
11func OpenTTY() (inTty, outTty *os.File, err error) {
12 return openTTY()
12 return openTTY()
13}
13}
14+
15+// Suspend suspends the current process group.
16+func Suspend() error {
17+ return suspend()
18+}
vendor/github.com/charmbracelet/ultraviolet/tty_other.go+4
@@ -8,3 +8,7 @@ import "os"
8func openTTY() (*os.File, *os.File, error) {
8func openTTY() (*os.File, *os.File, error) {
9 return nil, nil, ErrPlatformNotSupported
9 return nil, nil, ErrPlatformNotSupported
10}
10}
11+
12+func suspend() error {
13+ return ErrPlatformNotSupported
14+}
vendor/github.com/charmbracelet/ultraviolet/tty_unix.go+15−1
@@ -3,7 +3,11 @@
3
3
4package uv
4package uv
5
5
6−import "os"
6+import (
7+ "os"
8+ "os/signal"
9+ "syscall"
10+)
7
11
8func openTTY() (inTty, outTty *os.File, err error) {
12func openTTY() (inTty, outTty *os.File, err error) {
9 f, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
13 f, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
@@ -12,3 +16,13 @@ func openTTY() (inTty, outTty *os.File, err error) {
12 }
16 }
13 return f, f, nil
17 return f, f, nil
14}
18}
19+
20+func suspend() (err error) {
21+ // Send SIGTSTP to the entire process group.
22+ c := make(chan os.Signal, 1)
23+ signal.Notify(c, syscall.SIGCONT)
24+ err = syscall.Kill(0, syscall.SIGTSTP)
25+ // blocks until a CONT happens...
26+ <-c
27+ return
28+}
vendor/github.com/charmbracelet/ultraviolet/tty_windows.go+6
@@ -19,3 +19,9 @@ func openTTY() (inTty, outTty *os.File, err error) {
19 }
19 }
20 return inTty, outTty, nil
20 return inTty, outTty, nil
21}
21}
22+
23+func suspend() (err error) {
24+ // On Windows, suspending the process group is not supported in the same
25+ // way as Unix-like systems.
26+ return nil
27+}
vendor/github.com/mark3labs/mcp-go/client/client.go+425−75
@@ -1,84 +1,434 @@
1−// Package client provides MCP (Model Control Protocol) client implementations.
2package client
1package client
3
2
4import (
3import (
5 "context"
4 "context"
5+ "encoding/json"
6+ "errors"
7+ "fmt"
8+ "sync"
9+ "sync/atomic"
6
10
11+ "github.com/mark3labs/mcp-go/client/transport"
7 "github.com/mark3labs/mcp-go/mcp"
12 "github.com/mark3labs/mcp-go/mcp"
8)
13)
9
14
10−// MCPClient represents an MCP client interface
15+// Client implements the MCP client.
11−type MCPClient interface {
16+type Client struct {
12− // Initialize sends the initial connection request to the server
17+ transport transport.Interface
18+
19+ initialized bool
20+ notifications []func(mcp.JSONRPCNotification)
21+ notifyMu sync.RWMutex
22+ requestID atomic.Int64
23+ clientCapabilities mcp.ClientCapabilities
24+ serverCapabilities mcp.ServerCapabilities
25+}
26+
27+type ClientOption func(*Client)
28+
29+// WithClientCapabilities sets the client capabilities for the client.
30+func WithClientCapabilities(capabilities mcp.ClientCapabilities) ClientOption {
31+ return func(c *Client) {
32+ c.clientCapabilities = capabilities
33+ }
34+}
35+
36+// NewClient creates a new MCP client with the given transport.
37+// Usage:
38+//
39+// stdio := transport.NewStdio("./mcp_server", nil, "xxx")
40+// client, err := NewClient(stdio)
41+// if err != nil {
42+// log.Fatalf("Failed to create client: %v", err)
43+// }
44+func NewClient(transport transport.Interface, options ...ClientOption) *Client {
45+ client := &Client{
46+ transport: transport,
47+ }
48+
49+ for _, opt := range options {
50+ opt(client)
51+ }
52+
53+ return client
54+}
55+
56+// Start initiates the connection to the server.
57+// Must be called before using the client.
58+func (c *Client) Start(ctx context.Context) error {
59+ if c.transport == nil {
60+ return fmt.Errorf("transport is nil")
61+ }
62+ err := c.transport.Start(ctx)
63+ if err != nil {
64+ return err
65+ }
66+
67+ c.transport.SetNotificationHandler(func(notification mcp.JSONRPCNotification) {
68+ c.notifyMu.RLock()
69+ defer c.notifyMu.RUnlock()
70+ for _, handler := range c.notifications {
71+ handler(notification)
72+ }
73+ })
74+ return nil
75+}
76+
77+// Close shuts down the client and closes the transport.
78+func (c *Client) Close() error {
79+ return c.transport.Close()
80+}
81+
82+// OnNotification registers a handler function to be called when notifications are received.
83+// Multiple handlers can be registered and will be called in the order they were added.
84+func (c *Client) OnNotification(
85+ handler func(notification mcp.JSONRPCNotification),
86+) {
87+ c.notifyMu.Lock()
88+ defer c.notifyMu.Unlock()
89+ c.notifications = append(c.notifications, handler)
90+}
91+
92+// sendRequest sends a JSON-RPC request to the server and waits for a response.
93+// Returns the raw JSON response message or an error if the request fails.
94+func (c *Client) sendRequest(
95+ ctx context.Context,
96+ method string,
97+ params any,
98+) (*json.RawMessage, error) {
99+ if !c.initialized && method != "initialize" {
100+ return nil, fmt.Errorf("client not initialized")
101+ }
102+
103+ id := c.requestID.Add(1)
104+
105+ request := transport.JSONRPCRequest{
106+ JSONRPC: mcp.JSONRPC_VERSION,
107+ ID: mcp.NewRequestId(id),
108+ Method: method,
109+ Params: params,
110+ }
111+
112+ response, err := c.transport.SendRequest(ctx, request)
113+ if err != nil {
114+ return nil, fmt.Errorf("transport error: %w", err)
115+ }
116+
117+ if response.Error != nil {
118+ return nil, errors.New(response.Error.Message)
119+ }
120+
121+ return &response.Result, nil
122+}
123+
124+// Initialize negotiates with the server.
125+// Must be called after Start, and before any request methods.
13− Initialize(
126+func (c *Client) Initialize(
14− ctx context.Context,
127+ ctx context.Context,
15− request mcp.InitializeRequest,
128+ request mcp.InitializeRequest,
16− ) (*mcp.InitializeResult, error)
129+) (*mcp.InitializeResult, error) {
17−
130+ // Ensure we send a params object with all required fields
18− // Ping checks if the server is alive
131+ params := struct {
19− Ping(ctx context.Context) error
132+ ProtocolVersion string `json:"protocolVersion"`
20−
133+ ClientInfo mcp.Implementation `json:"clientInfo"`
21− // ListResources requests a list of available resources from the server
134+ Capabilities mcp.ClientCapabilities `json:"capabilities"`
22− ListResources(
135+ }{
136+ ProtocolVersion: request.Params.ProtocolVersion,
137+ ClientInfo: request.Params.ClientInfo,
138+ Capabilities: request.Params.Capabilities, // Will be empty struct if not set
139+ }
140+
141+ response, err := c.sendRequest(ctx, "initialize", params)
142+ if err != nil {
143+ return nil, err
144+ }
145+
146+ var result mcp.InitializeResult
147+ if err := json.Unmarshal(*response, &result); err != nil {
148+ return nil, fmt.Errorf("failed to unmarshal response: %w", err)
149+ }
150+
151+ // Store serverCapabilities
152+ c.serverCapabilities = result.Capabilities
153+
154+ // Send initialized notification
155+ notification := mcp.JSONRPCNotification{
156+ JSONRPC: mcp.JSONRPC_VERSION,
157+ Notification: mcp.Notification{
158+ Method: "notifications/initialized",
159+ },
160+ }
161+
162+ err = c.transport.SendNotification(ctx, notification)
163+ if err != nil {
164+ return nil, fmt.Errorf(
165+ "failed to send initialized notification: %w",
166+ err,
167+ )
168+ }
169+
170+ c.initialized = true
171+ return &result, nil
172+}
173+
174+func (c *Client) Ping(ctx context.Context) error {
175+ _, err := c.sendRequest(ctx, "ping", nil)
176+ return err
177+}
178+
179+// ListResourcesByPage manually list resources by page.
180+func (c *Client) ListResourcesByPage(
181+ ctx context.Context,
182+ request mcp.ListResourcesRequest,
183+) (*mcp.ListResourcesResult, error) {
184+ result, err := listByPage[mcp.ListResourcesResult](ctx, c, request.PaginatedRequest, "resources/list")
185+ if err != nil {
186+ return nil, err
187+ }
188+ return result, nil
189+}
190+
191+func (c *Client) ListResources(
192+ ctx context.Context,
193+ request mcp.ListResourcesRequest,
194+) (*mcp.ListResourcesResult, error) {
195+ result, err := c.ListResourcesByPage(ctx, request)
196+ if err != nil {
197+ return nil, err
198+ }
199+ for result.NextCursor != "" {
200+ select {
201+ case <-ctx.Done():
202+ return nil, ctx.Err()
203+ default:
204+ request.Params.Cursor = result.NextCursor
205+ newPageRes, err := c.ListResourcesByPage(ctx, request)
206+ if err != nil {
207+ return nil, err
208+ }
209+ result.Resources = append(result.Resources, newPageRes.Resources...)
210+ result.NextCursor = newPageRes.NextCursor
211+ }
212+ }
213+ return result, nil
214+}
215+
216+func (c *Client) ListResourceTemplatesByPage(
23− ctx context.Context,
217+ ctx context.Context,
24− request mcp.ListResourcesRequest,
218+ request mcp.ListResourceTemplatesRequest,
25− ) (*mcp.ListResourcesResult, error)
219+) (*mcp.ListResourceTemplatesResult, error) {
26−
220+ result, err := listByPage[mcp.ListResourceTemplatesResult](ctx, c, request.PaginatedRequest, "resources/templates/list")
27− // ListResourceTemplates requests a list of available resource templates from the server
221+ if err != nil {
222+ return nil, err
223+ }
224+ return result, nil
225+}
226+
28− ListResourceTemplates(
227+func (c *Client) ListResourceTemplates(
29− ctx context.Context,
228+ ctx context.Context,
30− request mcp.ListResourceTemplatesRequest,
229+ request mcp.ListResourceTemplatesRequest,
31− ) (*mcp.ListResourceTemplatesResult,
230+) (*mcp.ListResourceTemplatesResult, error) {
32− error)
231+ result, err := c.ListResourceTemplatesByPage(ctx, request)
33−
232+ if err != nil {
34− // ReadResource reads a specific resource from the server
233+ return nil, err
234+ }
235+ for result.NextCursor != "" {
236+ select {
237+ case <-ctx.Done():
238+ return nil, ctx.Err()
239+ default:
240+ request.Params.Cursor = result.NextCursor
241+ newPageRes, err := c.ListResourceTemplatesByPage(ctx, request)
242+ if err != nil {
243+ return nil, err
244+ }
245+ result.ResourceTemplates = append(result.ResourceTemplates, newPageRes.ResourceTemplates...)
246+ result.NextCursor = newPageRes.NextCursor
247+ }
248+ }
249+ return result, nil
250+}
251+
35− ReadResource(
252+func (c *Client) ReadResource(
36− ctx context.Context,
253+ ctx context.Context,
37− request mcp.ReadResourceRequest,
254+ request mcp.ReadResourceRequest,
38− ) (*mcp.ReadResourceResult, error)
255+) (*mcp.ReadResourceResult, error) {
39−
256+ response, err := c.sendRequest(ctx, "resources/read", request.Params)
40− // Subscribe requests notifications for changes to a specific resource
257+ if err != nil {
258+ return nil, err
259+ }
260+
261+ return mcp.ParseReadResourceResult(response)
262+}
263+
264+func (c *Client) Subscribe(
265+ ctx context.Context,
41− Subscribe(ctx context.Context, request mcp.SubscribeRequest) error
266+ request mcp.SubscribeRequest,
42−
267+) error {
43− // Unsubscribe cancels notifications for a specific resource
268+ _, err := c.sendRequest(ctx, "resources/subscribe", request.Params)
269+ return err
270+}
271+
272+func (c *Client) Unsubscribe(
273+ ctx context.Context,
44− Unsubscribe(ctx context.Context, request mcp.UnsubscribeRequest) error
274+ request mcp.UnsubscribeRequest,
45−
275+) error {
46− // ListPrompts requests a list of available prompts from the server
276+ _, err := c.sendRequest(ctx, "resources/unsubscribe", request.Params)
277+ return err
278+}
279+
280+func (c *Client) ListPromptsByPage(
281+ ctx context.Context,
282+ request mcp.ListPromptsRequest,
283+) (*mcp.ListPromptsResult, error) {
284+ result, err := listByPage[mcp.ListPromptsResult](ctx, c, request.PaginatedRequest, "prompts/list")
285+ if err != nil {
286+ return nil, err
287+ }
288+ return result, nil
289+}
290+
47− ListPrompts(
291+func (c *Client) ListPrompts(
48− ctx context.Context,
292+ ctx context.Context,
49− request mcp.ListPromptsRequest,
293+ request mcp.ListPromptsRequest,
50− ) (*mcp.ListPromptsResult, error)
294+) (*mcp.ListPromptsResult, error) {
51−
295+ result, err := c.ListPromptsByPage(ctx, request)
52− // GetPrompt retrieves a specific prompt from the server
296+ if err != nil {
297+ return nil, err
298+ }
299+ for result.NextCursor != "" {
300+ select {
301+ case <-ctx.Done():
302+ return nil, ctx.Err()
303+ default:
304+ request.Params.Cursor = result.NextCursor
305+ newPageRes, err := c.ListPromptsByPage(ctx, request)
306+ if err != nil {
307+ return nil, err
308+ }
309+ result.Prompts = append(result.Prompts, newPageRes.Prompts...)
310+ result.NextCursor = newPageRes.NextCursor
311+ }
312+ }
313+ return result, nil
314+}
315+
53− GetPrompt(
316+func (c *Client) GetPrompt(
54− ctx context.Context,
317+ ctx context.Context,
55− request mcp.GetPromptRequest,
318+ request mcp.GetPromptRequest,
56− ) (*mcp.GetPromptResult, error)
319+) (*mcp.GetPromptResult, error) {
57−
320+ response, err := c.sendRequest(ctx, "prompts/get", request.Params)
58− // ListTools requests a list of available tools from the server
321+ if err != nil {
322+ return nil, err
323+ }
324+
325+ return mcp.ParseGetPromptResult(response)
326+}
327+
328+func (c *Client) ListToolsByPage(
329+ ctx context.Context,
330+ request mcp.ListToolsRequest,
331+) (*mcp.ListToolsResult, error) {
332+ result, err := listByPage[mcp.ListToolsResult](ctx, c, request.PaginatedRequest, "tools/list")
333+ if err != nil {
334+ return nil, err
335+ }
336+ return result, nil
337+}
338+
59− ListTools(
339+func (c *Client) ListTools(
60− ctx context.Context,
340+ ctx context.Context,
61− request mcp.ListToolsRequest,
341+ request mcp.ListToolsRequest,
62− ) (*mcp.ListToolsResult, error)
342+) (*mcp.ListToolsResult, error) {
63−
343+ result, err := c.ListToolsByPage(ctx, request)
64− // CallTool invokes a specific tool on the server
344+ if err != nil {
345+ return nil, err
346+ }
347+ for result.NextCursor != "" {
348+ select {
349+ case <-ctx.Done():
350+ return nil, ctx.Err()
351+ default:
352+ request.Params.Cursor = result.NextCursor
353+ newPageRes, err := c.ListToolsByPage(ctx, request)
354+ if err != nil {
355+ return nil, err
356+ }
357+ result.Tools = append(result.Tools, newPageRes.Tools...)
358+ result.NextCursor = newPageRes.NextCursor
359+ }
360+ }
361+ return result, nil
362+}
363+
65− CallTool(
364+func (c *Client) CallTool(
66− ctx context.Context,
365+ ctx context.Context,
67− request mcp.CallToolRequest,
366+ request mcp.CallToolRequest,
68− ) (*mcp.CallToolResult, error)
367+) (*mcp.CallToolResult, error) {
69−
368+ response, err := c.sendRequest(ctx, "tools/call", request.Params)
70− // SetLevel sets the logging level for the server
369+ if err != nil {
370+ return nil, err
371+ }
372+
373+ return mcp.ParseCallToolResult(response)
374+}
375+
376+func (c *Client) SetLevel(
377+ ctx context.Context,
71− SetLevel(ctx context.Context, request mcp.SetLevelRequest) error
378+ request mcp.SetLevelRequest,
72−
379+) error {
73− // Complete requests completion options for a given argument
380+ _, err := c.sendRequest(ctx, "logging/setLevel", request.Params)
381+ return err
382+}
383+
74− Complete(
384+func (c *Client) Complete(
75− ctx context.Context,
385+ ctx context.Context,
76− request mcp.CompleteRequest,
386+ request mcp.CompleteRequest,
77− ) (*mcp.CompleteResult, error)
387+) (*mcp.CompleteResult, error) {
78−
388+ response, err := c.sendRequest(ctx, "completion/complete", request.Params)
79− // Close client connection and cleanup resources
389+ if err != nil {
390+ return nil, err
391+ }
392+
393+ var result mcp.CompleteResult
394+ if err := json.Unmarshal(*response, &result); err != nil {
395+ return nil, fmt.Errorf("failed to unmarshal response: %w", err)
396+ }
397+
398+ return &result, nil
399+}
400+
401+func listByPage[T any](
402+ ctx context.Context,
403+ client *Client,
404+ request mcp.PaginatedRequest,
405+ method string,
80− Close() error
406+) (*T, error) {
81−
407+ response, err := client.sendRequest(ctx, method, request.Params)
82− // OnNotification registers a handler for notifications
408+ if err != nil {
83− OnNotification(handler func(notification mcp.JSONRPCNotification))
409+ return nil, err
410+ }
411+ var result T
412+ if err := json.Unmarshal(*response, &result); err != nil {
413+ return nil, fmt.Errorf("failed to unmarshal response: %w", err)
414+ }
415+ return &result, nil
416+}
417+
418+// Helper methods
419+
420+// GetTransport gives access to the underlying transport layer.
421+// Cast it to the specific transport type and obtain the other helper methods.
422+func (c *Client) GetTransport() transport.Interface {
423+ return c.transport
424+}
425+
426+// GetServerCapabilities returns the server capabilities.
427+func (c *Client) GetServerCapabilities() mcp.ServerCapabilities {
428+ return c.serverCapabilities
429+}
430+
431+// GetClientCapabilities returns the client capabilities.
432+func (c *Client) GetClientCapabilities() mcp.ClientCapabilities {
433+ return c.clientCapabilities
84}
434}
vendor/github.com/mark3labs/mcp-go/client/http.gonew file+17
@@ -0,0 +1,17 @@
1+package client
2+
3+import (
4+ "fmt"
5+
6+ "github.com/mark3labs/mcp-go/client/transport"
7+)
8+
9+// NewStreamableHttpClient is a convenience method that creates a new streamable-http-based MCP client
10+// with the given base URL. Returns an error if the URL is invalid.
11+func NewStreamableHttpClient(baseURL string, options ...transport.StreamableHTTPCOption) (*Client, error) {
12+ trans, err := transport.NewStreamableHTTP(baseURL, options...)
13+ if err != nil {
14+ return nil, fmt.Errorf("failed to create SSE transport: %w", err)
15+ }
16+ return NewClient(trans), nil
17+}
vendor/github.com/mark3labs/mcp-go/client/inprocess.gonew file+12
@@ -0,0 +1,12 @@
1+package client
2+
3+import (
4+ "github.com/mark3labs/mcp-go/client/transport"
5+ "github.com/mark3labs/mcp-go/server"
6+)
7+
8+// NewInProcessClient connect directly to a mcp server object in the same process
9+func NewInProcessClient(server *server.MCPServer) (*Client, error) {
10+ inProcessTransport := transport.NewInProcessTransport(server)
11+ return NewClient(inProcessTransport), nil
12+}
vendor/github.com/mark3labs/mcp-go/client/interface.gonew file+109
@@ -0,0 +1,109 @@
1+// Package client provides MCP (Model Context Protocol) client implementations.
2+package client
3+
4+import (
5+ "context"
6+
7+ "github.com/mark3labs/mcp-go/mcp"
8+)
9+
10+// MCPClient represents an MCP client interface
11+type MCPClient interface {
12+ // Initialize sends the initial connection request to the server
13+ Initialize(
14+ ctx context.Context,
15+ request mcp.InitializeRequest,
16+ ) (*mcp.InitializeResult, error)
17+
18+ // Ping checks if the server is alive
19+ Ping(ctx context.Context) error
20+
21+ // ListResourcesByPage manually list resources by page.
22+ ListResourcesByPage(
23+ ctx context.Context,
24+ request mcp.ListResourcesRequest,
25+ ) (*mcp.ListResourcesResult, error)
26+
27+ // ListResources requests a list of available resources from the server
28+ ListResources(
29+ ctx context.Context,
30+ request mcp.ListResourcesRequest,
31+ ) (*mcp.ListResourcesResult, error)
32+
33+ // ListResourceTemplatesByPage manually list resource templates by page.
34+ ListResourceTemplatesByPage(
35+ ctx context.Context,
36+ request mcp.ListResourceTemplatesRequest,
37+ ) (*mcp.ListResourceTemplatesResult,
38+ error)
39+
40+ // ListResourceTemplates requests a list of available resource templates from the server
41+ ListResourceTemplates(
42+ ctx context.Context,
43+ request mcp.ListResourceTemplatesRequest,
44+ ) (*mcp.ListResourceTemplatesResult,
45+ error)
46+
47+ // ReadResource reads a specific resource from the server
48+ ReadResource(
49+ ctx context.Context,
50+ request mcp.ReadResourceRequest,
51+ ) (*mcp.ReadResourceResult, error)
52+
53+ // Subscribe requests notifications for changes to a specific resource
54+ Subscribe(ctx context.Context, request mcp.SubscribeRequest) error
55+
56+ // Unsubscribe cancels notifications for a specific resource
57+ Unsubscribe(ctx context.Context, request mcp.UnsubscribeRequest) error
58+
59+ // ListPromptsByPage manually list prompts by page.
60+ ListPromptsByPage(
61+ ctx context.Context,
62+ request mcp.ListPromptsRequest,
63+ ) (*mcp.ListPromptsResult, error)
64+
65+ // ListPrompts requests a list of available prompts from the server
66+ ListPrompts(
67+ ctx context.Context,
68+ request mcp.ListPromptsRequest,
69+ ) (*mcp.ListPromptsResult, error)
70+
71+ // GetPrompt retrieves a specific prompt from the server
72+ GetPrompt(
73+ ctx context.Context,
74+ request mcp.GetPromptRequest,
75+ ) (*mcp.GetPromptResult, error)
76+
77+ // ListToolsByPage manually list tools by page.
78+ ListToolsByPage(
79+ ctx context.Context,
80+ request mcp.ListToolsRequest,
81+ ) (*mcp.ListToolsResult, error)
82+
83+ // ListTools requests a list of available tools from the server
84+ ListTools(
85+ ctx context.Context,
86+ request mcp.ListToolsRequest,
87+ ) (*mcp.ListToolsResult, error)
88+
89+ // CallTool invokes a specific tool on the server
90+ CallTool(
91+ ctx context.Context,
92+ request mcp.CallToolRequest,
93+ ) (*mcp.CallToolResult, error)
94+
95+ // SetLevel sets the logging level for the server
96+ SetLevel(ctx context.Context, request mcp.SetLevelRequest) error
97+
98+ // Complete requests completion options for a given argument
99+ Complete(
100+ ctx context.Context,
101+ request mcp.CompleteRequest,
102+ ) (*mcp.CompleteResult, error)
103+
104+ // Close client connection and cleanup resources
105+ Close() error
106+
107+ // OnNotification registers a handler for notifications
108+ OnNotification(handler func(notification mcp.JSONRPCNotification))
109+}
vendor/github.com/mark3labs/mcp-go/client/oauth.gonew file+76
@@ -0,0 +1,76 @@
1+package client
2+
3+import (
4+ "errors"
5+ "fmt"
6+
7+ "github.com/mark3labs/mcp-go/client/transport"
8+)
9+
10+// OAuthConfig is a convenience type that wraps transport.OAuthConfig
11+type OAuthConfig = transport.OAuthConfig
12+
13+// Token is a convenience type that wraps transport.Token
14+type Token = transport.Token
15+
16+// TokenStore is a convenience type that wraps transport.TokenStore
17+type TokenStore = transport.TokenStore
18+
19+// MemoryTokenStore is a convenience type that wraps transport.MemoryTokenStore
20+type MemoryTokenStore = transport.MemoryTokenStore
21+
22+// NewMemoryTokenStore is a convenience function that wraps transport.NewMemoryTokenStore
23+var NewMemoryTokenStore = transport.NewMemoryTokenStore
24+
25+// NewOAuthStreamableHttpClient creates a new streamable-http-based MCP client with OAuth support.
26+// Returns an error if the URL is invalid.
27+func NewOAuthStreamableHttpClient(baseURL string, oauthConfig OAuthConfig, options ...transport.StreamableHTTPCOption) (*Client, error) {
28+ // Add OAuth option to the list of options
29+ options = append(options, transport.WithHTTPOAuth(oauthConfig))
30+
31+ trans, err := transport.NewStreamableHTTP(baseURL, options...)
32+ if err != nil {
33+ return nil, fmt.Errorf("failed to create HTTP transport: %w", err)
34+ }
35+ return NewClient(trans), nil
36+}
37+
38+// NewOAuthStreamableHttpClient creates a new streamable-http-based MCP client with OAuth support.
39+// Returns an error if the URL is invalid.
40+func NewOAuthSSEClient(baseURL string, oauthConfig OAuthConfig, options ...transport.ClientOption) (*Client, error) {
41+ // Add OAuth option to the list of options
42+ options = append(options, transport.WithOAuth(oauthConfig))
43+
44+ trans, err := transport.NewSSE(baseURL, options...)
45+ if err != nil {
46+ return nil, fmt.Errorf("failed to create SSE transport: %w", err)
47+ }
48+ return NewClient(trans), nil
49+}
50+
51+// GenerateCodeVerifier generates a code verifier for PKCE
52+var GenerateCodeVerifier = transport.GenerateCodeVerifier
53+
54+// GenerateCodeChallenge generates a code challenge from a code verifier
55+var GenerateCodeChallenge = transport.GenerateCodeChallenge
56+
57+// GenerateState generates a state parameter for OAuth
58+var GenerateState = transport.GenerateState
59+
60+// OAuthAuthorizationRequiredError is returned when OAuth authorization is required
61+type OAuthAuthorizationRequiredError = transport.OAuthAuthorizationRequiredError
62+
63+// IsOAuthAuthorizationRequiredError checks if an error is an OAuthAuthorizationRequiredError
64+func IsOAuthAuthorizationRequiredError(err error) bool {
65+ var target *OAuthAuthorizationRequiredError
66+ return errors.As(err, &target)
67+}
68+
69+// GetOAuthHandler extracts the OAuthHandler from an OAuthAuthorizationRequiredError
70+func GetOAuthHandler(err error) *transport.OAuthHandler {
71+ var oauthErr *OAuthAuthorizationRequiredError
72+ if errors.As(err, &oauthErr) {
73+ return oauthErr.Handler
74+ }
75+ return nil
76+}
vendor/github.com/mark3labs/mcp-go/client/sse.go+17−563
@@ -1,588 +1,42 @@
1package client
1package client
2
2
3import (
3import (
4− "bufio"
5− "bytes"
6− "context"
7− "encoding/json"
8− "errors"
9 "fmt"
4 "fmt"
10− "io"
11 "net/http"
5 "net/http"
12 "net/url"
6 "net/url"
13− "strings"
14− "sync"
15− "sync/atomic"
16− "time"
17
7
18− "github.com/mark3labs/mcp-go/mcp"
8+ "github.com/mark3labs/mcp-go/client/transport"
19)
9)
20
10
21−// SSEMCPClient implements the MCPClient interface using Server-Sent Events (SSE).
22−// It maintains a persistent HTTP connection to receive server-pushed events
23−// while sending requests over regular HTTP POST calls. The client handles
24−// automatic reconnection and message routing between requests and responses.
25−type SSEMCPClient struct {
26− baseURL *url.URL
27− endpoint *url.URL
28− httpClient *http.Client
29− requestID atomic.Int64
30− responses map[int64]chan RPCResponse
31− mu sync.RWMutex
32− done chan struct{}
33− initialized bool
34− notifications []func(mcp.JSONRPCNotification)
35− notifyMu sync.RWMutex
36− endpointChan chan struct{}
37− capabilities mcp.ServerCapabilities
38− headers map[string]string
11+func WithHeaders(headers map[string]string) transport.ClientOption {
39− sseReadTimeout time.Duration
12+ return transport.WithHeaders(headers)
40}
13}
41
14
42−type ClientOption func(*SSEMCPClient)
15+func WithHeaderFunc(headerFunc transport.HTTPHeaderFunc) transport.ClientOption {
43−
16+ return transport.WithHeaderFunc(headerFunc)
44−func WithHeaders(headers map[string]string) ClientOption {
45− return func(sc *SSEMCPClient) {
46− sc.headers = headers
47− }
48}
17}
49
18
50−func WithSSEReadTimeout(timeout time.Duration) ClientOption {
19+func WithHTTPClient(httpClient *http.Client) transport.ClientOption {
51− return func(sc *SSEMCPClient) {
20+ return transport.WithHTTPClient(httpClient)
52− sc.sseReadTimeout = timeout
53− }
54}
21}
55
22
56// NewSSEMCPClient creates a new SSE-based MCP client with the given base URL.
23// NewSSEMCPClient creates a new SSE-based MCP client with the given base URL.
57// Returns an error if the URL is invalid.
24// Returns an error if the URL is invalid.
58−func NewSSEMCPClient(baseURL string, options ...ClientOption) (*SSEMCPClient, error) {
25+func NewSSEMCPClient(baseURL string, options ...transport.ClientOption) (*Client, error) {
59− parsedURL, err := url.Parse(baseURL)
60− if err != nil {
61− return nil, fmt.Errorf("invalid URL: %w", err)
62− }
63−
64− smc := &SSEMCPClient{
65− baseURL: parsedURL,
66− httpClient: &http.Client{},
67− responses: make(map[int64]chan RPCResponse),
68− done: make(chan struct{}),
69− endpointChan: make(chan struct{}),
70− sseReadTimeout: 30 * time.Second,
71− headers: make(map[string]string),
72− }
73−
74− for _, opt := range options {
75− opt(smc)
76− }
77−
78− return smc, nil
79−}
80−
81−// Start initiates the SSE connection to the server and waits for the endpoint information.
82−// Returns an error if the connection fails or times out waiting for the endpoint.
83−func (c *SSEMCPClient) Start(ctx context.Context) error {
84−
85− req, err := http.NewRequestWithContext(ctx, "GET", c.baseURL.String(), nil)
86−
87− if err != nil {
88−
89− return fmt.Errorf("failed to create request: %w", err)
90−
91− }
92−
93− req.Header.Set("Accept", "text/event-stream")
94− req.Header.Set("Cache-Control", "no-cache")
95− req.Header.Set("Connection", "keep-alive")
96−
97− resp, err := c.httpClient.Do(req)
98− if err != nil {
99− return fmt.Errorf("failed to connect to SSE stream: %w", err)
100− }
101−
102− if resp.StatusCode != http.StatusOK {
103− resp.Body.Close()
104− return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
105− }
106−
107− go c.readSSE(resp.Body)
108−
109− // Wait for the endpoint to be received
110−
111− select {
112− case <-c.endpointChan:
113− // Endpoint received, proceed
114− case <-ctx.Done():
115− return fmt.Errorf("context cancelled while waiting for endpoint")
116− case <-time.After(30 * time.Second): // Add a timeout
117− return fmt.Errorf("timeout waiting for endpoint")
118− }
119−
120− return nil
121−}
122−
123−// readSSE continuously reads the SSE stream and processes events.
124−// It runs until the connection is closed or an error occurs.
125−func (c *SSEMCPClient) readSSE(reader io.ReadCloser) {
126− defer reader.Close()
127−
128− br := bufio.NewReader(reader)
129− var event, data string
130−
131− ctx, cancel := context.WithTimeout(context.Background(), c.sseReadTimeout)
132− defer cancel()
133−
134− for {
135− select {
136− case <-ctx.Done():
137− return
138− default:
139− line, err := br.ReadString('\n')
140− if err != nil {
141− if err == io.EOF {
142− // Process any pending event before exit
143− if event != "" && data != "" {
144− c.handleSSEEvent(event, data)
145− }
146− break
147− }
148− select {
149− case <-c.done:
150− return
151− default:
152− fmt.Printf("SSE stream error: %v\n", err)
153− return
154− }
155− }
156−
157− // Remove only newline markers
158− line = strings.TrimRight(line, "\r\n")
159− if line == "" {
160− // Empty line means end of event
161− if event != "" && data != "" {
162− c.handleSSEEvent(event, data)
163− event = ""
164− data = ""
165− }
166− continue
167− }
168−
169− if strings.HasPrefix(line, "event:") {
170− event = strings.TrimSpace(strings.TrimPrefix(line, "event:"))
171− } else if strings.HasPrefix(line, "data:") {
172− data = strings.TrimSpace(strings.TrimPrefix(line, "data:"))
173− }
174− }
175− }
176−}
177−
178−// handleSSEEvent processes SSE events based on their type.
179−// Handles 'endpoint' events for connection setup and 'message' events for JSON-RPC communication.
180−func (c *SSEMCPClient) handleSSEEvent(event, data string) {
181− switch event {
182− case "endpoint":
183− endpoint, err := c.baseURL.Parse(data)
184− if err != nil {
185− fmt.Printf("Error parsing endpoint URL: %v\n", err)
186− return
187− }
188− if endpoint.Host != c.baseURL.Host {
189− fmt.Printf("Endpoint origin does not match connection origin\n")
190− return
191− }
192− c.endpoint = endpoint
193− close(c.endpointChan)
194−
195− case "message":
196− var baseMessage struct {
197− JSONRPC string `json:"jsonrpc"`
198− ID *int64 `json:"id,omitempty"`
199− Method string `json:"method,omitempty"`
200− Result json.RawMessage `json:"result,omitempty"`
201− Error *struct {
202− Code int `json:"code"`
203− Message string `json:"message"`
204− } `json:"error,omitempty"`
205− }
206−
207− if err := json.Unmarshal([]byte(data), &baseMessage); err != nil {
208− fmt.Printf("Error unmarshaling message: %v\n", err)
209− return
210− }
211−
212− // Handle notification
213− if baseMessage.ID == nil {
214− var notification mcp.JSONRPCNotification
215− if err := json.Unmarshal([]byte(data), &notification); err != nil {
216− return
217− }
218− c.notifyMu.RLock()
219− for _, handler := range c.notifications {
220− handler(notification)
221− }
222− c.notifyMu.RUnlock()
223− return
224− }
225−
226− c.mu.RLock()
227− ch, ok := c.responses[*baseMessage.ID]
228− c.mu.RUnlock()
229−
230− if ok {
231− if baseMessage.Error != nil {
232− ch <- RPCResponse{
233− Error: &baseMessage.Error.Message,
234− }
235− } else {
236− ch <- RPCResponse{
237− Response: &baseMessage.Result,
238− }
239− }
240− c.mu.Lock()
241− delete(c.responses, *baseMessage.ID)
242− c.mu.Unlock()
243− }
244− }
245−}
246−
247−// OnNotification registers a handler function to be called when notifications are received.
248−// Multiple handlers can be registered and will be called in the order they were added.
249−func (c *SSEMCPClient) OnNotification(
250− handler func(notification mcp.JSONRPCNotification),
251−) {
252− c.notifyMu.Lock()
253− defer c.notifyMu.Unlock()
254− c.notifications = append(c.notifications, handler)
255−}
256−
257−// sendRequest sends a JSON-RPC request to the server and waits for a response.
258−// Returns the raw JSON response message or an error if the request fails.
259−func (c *SSEMCPClient) sendRequest(
260− ctx context.Context,
261− method string,
262− params interface{},
263−) (*json.RawMessage, error) {
264− if !c.initialized && method != "initialize" {
265− return nil, fmt.Errorf("client not initialized")
266− }
267−
268− if c.endpoint == nil {
269− return nil, fmt.Errorf("endpoint not received")
270− }
271−
272− id := c.requestID.Add(1)
273−
274− request := mcp.JSONRPCRequest{
275− JSONRPC: mcp.JSONRPC_VERSION,
276− ID: id,
277− Request: mcp.Request{
278− Method: method,
279− },
280− Params: params,
281− }
282−
283− requestBytes, err := json.Marshal(request)
284− if err != nil {
285− return nil, fmt.Errorf("failed to marshal request: %w", err)
286− }
287−
288− responseChan := make(chan RPCResponse, 1)
289− c.mu.Lock()
290− c.responses[id] = responseChan
291− c.mu.Unlock()
292−
293− req, err := http.NewRequestWithContext(
294− ctx,
295− "POST",
296− c.endpoint.String(),
297− bytes.NewReader(requestBytes),
298− )
299− if err != nil {
300− return nil, fmt.Errorf("failed to create request: %w", err)
301− }
302−
303− req.Header.Set("Content-Type", "application/json")
304− // set custom http headers
305− for k, v := range c.headers {
306− req.Header.Set(k, v)
307− }
308−
309− resp, err := c.httpClient.Do(req)
310− if err != nil {
311− return nil, fmt.Errorf("failed to send request: %w", err)
312− }
313− defer resp.Body.Close()
314−
315− if resp.StatusCode != http.StatusOK &&
316− resp.StatusCode != http.StatusAccepted {
317− body, _ := io.ReadAll(resp.Body)
318− return nil, fmt.Errorf(
319− "request failed with status %d: %s",
320− resp.StatusCode,
321− body,
322− )
323− }
324−
325− select {
326− case <-ctx.Done():
327− c.mu.Lock()
328− delete(c.responses, id)
329− c.mu.Unlock()
330− return nil, ctx.Err()
331− case response := <-responseChan:
332− if response.Error != nil {
333− return nil, errors.New(*response.Error)
334− }
335− return response.Response, nil
336− }
337−}
338−
339−func (c *SSEMCPClient) Initialize(
340− ctx context.Context,
341− request mcp.InitializeRequest,
342−) (*mcp.InitializeResult, error) {
343− // Ensure we send a params object with all required fields
344− params := struct {
345− ProtocolVersion string `json:"protocolVersion"`
346− ClientInfo mcp.Implementation `json:"clientInfo"`
347− Capabilities mcp.ClientCapabilities `json:"capabilities"`
348− }{
349− ProtocolVersion: request.Params.ProtocolVersion,
350− ClientInfo: request.Params.ClientInfo,
351− Capabilities: request.Params.Capabilities, // Will be empty struct if not set
352− }
353−
354− response, err := c.sendRequest(ctx, "initialize", params)
355− if err != nil {
356− return nil, err
357− }
358
26
359− var result mcp.InitializeResult
27+ sseTransport, err := transport.NewSSE(baseURL, options...)
360− if err := json.Unmarshal(*response, &result); err != nil {
361− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
362− }
363−
364− // Store capabilities
365− c.capabilities = result.Capabilities
366−
367− // Send initialized notification
368− notification := mcp.JSONRPCNotification{
369− JSONRPC: mcp.JSONRPC_VERSION,
370− Notification: mcp.Notification{
371− Method: "notifications/initialized",
372− },
373− }
374−
375− notificationBytes, err := json.Marshal(notification)
376− if err != nil {
377− return nil, fmt.Errorf(
378− "failed to marshal initialized notification: %w",
379− err,
380− )
381− }
382−
383− req, err := http.NewRequestWithContext(
384− ctx,
385− "POST",
386− c.endpoint.String(),
387− bytes.NewReader(notificationBytes),
388− )
389− if err != nil {
390− return nil, fmt.Errorf("failed to create notification request: %w", err)
391− }
392−
393− req.Header.Set("Content-Type", "application/json")
394−
395− resp, err := c.httpClient.Do(req)
396 if err != nil {
28 if err != nil {
397− return nil, fmt.Errorf(
29+ return nil, fmt.Errorf("failed to create SSE transport: %w", err)
398− "failed to send initialized notification: %w",
399− err,
400− )
401 }
30 }
402− resp.Body.Close()
403
31
404− c.initialized = true
405− return &result, nil
32+ return NewClient(sseTransport), nil
406}
33}
407
34
408−func (c *SSEMCPClient) Ping(ctx context.Context) error {
409− _, err := c.sendRequest(ctx, "ping", nil)
410− return err
411−}
412−
413−func (c *SSEMCPClient) ListResources(
414− ctx context.Context,
415− request mcp.ListResourcesRequest,
416−) (*mcp.ListResourcesResult, error) {
417− response, err := c.sendRequest(ctx, "resources/list", request.Params)
418− if err != nil {
419− return nil, err
420− }
421−
422− var result mcp.ListResourcesResult
423− if err := json.Unmarshal(*response, &result); err != nil {
424− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
425− }
426−
427− return &result, nil
428−}
429−
430−func (c *SSEMCPClient) ListResourceTemplates(
431− ctx context.Context,
432− request mcp.ListResourceTemplatesRequest,
433−) (*mcp.ListResourceTemplatesResult, error) {
434− response, err := c.sendRequest(
435− ctx,
436− "resources/templates/list",
437− request.Params,
438− )
439− if err != nil {
440− return nil, err
441− }
442−
443− var result mcp.ListResourceTemplatesResult
444− if err := json.Unmarshal(*response, &result); err != nil {
445− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
446− }
447−
448− return &result, nil
449−}
450−
451−func (c *SSEMCPClient) ReadResource(
452− ctx context.Context,
453− request mcp.ReadResourceRequest,
454−) (*mcp.ReadResourceResult, error) {
455− response, err := c.sendRequest(ctx, "resources/read", request.Params)
456− if err != nil {
457− return nil, err
458− }
459−
460− return mcp.ParseReadResourceResult(response)
461−}
462−
463−func (c *SSEMCPClient) Subscribe(
464− ctx context.Context,
465− request mcp.SubscribeRequest,
466−) error {
467− _, err := c.sendRequest(ctx, "resources/subscribe", request.Params)
468− return err
469−}
470−
471−func (c *SSEMCPClient) Unsubscribe(
472− ctx context.Context,
473− request mcp.UnsubscribeRequest,
474−) error {
475− _, err := c.sendRequest(ctx, "resources/unsubscribe", request.Params)
476− return err
477−}
478−
479−func (c *SSEMCPClient) ListPrompts(
480− ctx context.Context,
481− request mcp.ListPromptsRequest,
482−) (*mcp.ListPromptsResult, error) {
483− response, err := c.sendRequest(ctx, "prompts/list", request.Params)
484− if err != nil {
485− return nil, err
486− }
487−
488− var result mcp.ListPromptsResult
489− if err := json.Unmarshal(*response, &result); err != nil {
490− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
491− }
492−
493− return &result, nil
494−}
495−
496−func (c *SSEMCPClient) GetPrompt(
497− ctx context.Context,
498− request mcp.GetPromptRequest,
499−) (*mcp.GetPromptResult, error) {
500− response, err := c.sendRequest(ctx, "prompts/get", request.Params)
501− if err != nil {
502− return nil, err
503− }
504−
505− return mcp.ParseGetPromptResult(response)
506−}
507−
508−func (c *SSEMCPClient) ListTools(
509− ctx context.Context,
510− request mcp.ListToolsRequest,
511−) (*mcp.ListToolsResult, error) {
512− response, err := c.sendRequest(ctx, "tools/list", request.Params)
513− if err != nil {
514− return nil, err
515− }
516−
517− var result mcp.ListToolsResult
518− if err := json.Unmarshal(*response, &result); err != nil {
519− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
520− }
521−
522− return &result, nil
523−}
524−
525−func (c *SSEMCPClient) CallTool(
526− ctx context.Context,
527− request mcp.CallToolRequest,
528−) (*mcp.CallToolResult, error) {
529− response, err := c.sendRequest(ctx, "tools/call", request.Params)
530− if err != nil {
531− return nil, err
532− }
533−
534− return mcp.ParseCallToolResult(response)
535−}
536−
537−func (c *SSEMCPClient) SetLevel(
538− ctx context.Context,
539− request mcp.SetLevelRequest,
540−) error {
541− _, err := c.sendRequest(ctx, "logging/setLevel", request.Params)
542− return err
543−}
544−
545−func (c *SSEMCPClient) Complete(
546− ctx context.Context,
547− request mcp.CompleteRequest,
548−) (*mcp.CompleteResult, error) {
549− response, err := c.sendRequest(ctx, "completion/complete", request.Params)
550− if err != nil {
551− return nil, err
552− }
553−
554− var result mcp.CompleteResult
555− if err := json.Unmarshal(*response, &result); err != nil {
556− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
557− }
558−
559− return &result, nil
560−}
561−
562−// Helper methods
563−
564// GetEndpoint returns the current endpoint URL for the SSE connection.
35// GetEndpoint returns the current endpoint URL for the SSE connection.
565−func (c *SSEMCPClient) GetEndpoint() *url.URL {
36+//
566− return c.endpoint
37+// Note: This method only works with SSE transport, or it will panic.
567−}
38+func GetEndpoint(c *Client) *url.URL {
568−
39+ t := c.GetTransport()
569−// Close shuts down the SSE client connection and cleans up any pending responses.
40+ sse := t.(*transport.SSE)
570−// Returns an error if the shutdown process fails.
41+ return sse.GetEndpoint()
571−func (c *SSEMCPClient) Close() error {
572− select {
573− case <-c.done:
574− return nil // Already closed
575− default:
576− close(c.done)
577− }
578−
579− // Clean up any pending responses
580− c.mu.Lock()
581− for _, ch := range c.responses {
582− close(ch)
583− }
584− c.responses = make(map[int64]chan RPCResponse)
585− c.mu.Unlock()
586−
587− return nil
588}
42}
vendor/github.com/mark3labs/mcp-go/client/stdio.go+17−415
@@ -1,441 +1,43 @@
1package client
1package client
2
2
3import (
3import (
4− "bufio"
5 "context"
4 "context"
6− "encoding/json"
7− "errors"
8 "fmt"
5 "fmt"
9 "io"
6 "io"
10− "os"
11− "os/exec"
12− "sync"
13− "sync/atomic"
14
7
15− "github.com/mark3labs/mcp-go/mcp"
8+ "github.com/mark3labs/mcp-go/client/transport"
16)
9)
17
10
18−// StdioMCPClient implements the MCPClient interface using stdio communication.
19−// It launches a subprocess and communicates with it via standard input/output streams
20−// using JSON-RPC messages. The client handles message routing between requests and
21−// responses, and supports asynchronous notifications.
22−type StdioMCPClient struct {
23− cmd *exec.Cmd
24− stdin io.WriteCloser
25− stdout *bufio.Reader
26− requestID atomic.Int64
27− responses map[int64]chan RPCResponse
28− mu sync.RWMutex
29− done chan struct{}
30− initialized bool
31− notifications []func(mcp.JSONRPCNotification)
32− notifyMu sync.RWMutex
33− capabilities mcp.ServerCapabilities
34−}
35−
36// NewStdioMCPClient creates a new stdio-based MCP client that communicates with a subprocess.
11// NewStdioMCPClient creates a new stdio-based MCP client that communicates with a subprocess.
37// It launches the specified command with given arguments and sets up stdin/stdout pipes for communication.
12// It launches the specified command with given arguments and sets up stdin/stdout pipes for communication.
38// Returns an error if the subprocess cannot be started or the pipes cannot be created.
13// Returns an error if the subprocess cannot be started or the pipes cannot be created.
14+//
15+// NOTICE: NewStdioMCPClient will start the connection automatically. Don't call the Start method manually.
16+// This is for backward compatibility.
39func NewStdioMCPClient(
17func NewStdioMCPClient(
40 command string,
18 command string,
41 env []string,
19 env []string,
42 args ...string,
20 args ...string,
43−) (*StdioMCPClient, error) {
21+) (*Client, error) {
44− cmd := exec.Command(command, args...)
45−
46− mergedEnv := os.Environ()
47− mergedEnv = append(mergedEnv, env...)
48−
49− cmd.Env = mergedEnv
50−
51− stdin, err := cmd.StdinPipe()
52− if err != nil {
53− return nil, fmt.Errorf("failed to create stdin pipe: %w", err)
54− }
55
22
56− stdout, err := cmd.StdoutPipe()
23+ stdioTransport := transport.NewStdio(command, env, args...)
24+ err := stdioTransport.Start(context.Background())
57 if err != nil {
25 if err != nil {
58− return nil, fmt.Errorf("failed to create stdout pipe: %w", err)
26+ return nil, fmt.Errorf("failed to start stdio transport: %w", err)
59− }
60−
61− client := &StdioMCPClient{
62− cmd: cmd,
63− stdin: stdin,
64− stdout: bufio.NewReader(stdout),
65− responses: make(map[int64]chan RPCResponse),
66− done: make(chan struct{}),
67− }
68−
69− if err := cmd.Start(); err != nil {
70− return nil, fmt.Errorf("failed to start command: %w", err)
71− }
72−
73− // Start reading responses in a goroutine and wait for it to be ready
74− ready := make(chan struct{})
75− go func() {
76− close(ready)
77− client.readResponses()
78− }()
79− <-ready
80−
81− return client, nil
82−}
83−
84−// Close shuts down the stdio client, closing the stdin pipe and waiting for the subprocess to exit.
85−// Returns an error if there are issues closing stdin or waiting for the subprocess to terminate.
86−func (c *StdioMCPClient) Close() error {
87− close(c.done)
88− if err := c.stdin.Close(); err != nil {
89− return fmt.Errorf("failed to close stdin: %w", err)
90 }
27 }
91− return c.cmd.Wait()
92−}
93−
94−// OnNotification registers a handler function to be called when notifications are received.
95−// Multiple handlers can be registered and will be called in the order they were added.
96−func (c *StdioMCPClient) OnNotification(
97− handler func(notification mcp.JSONRPCNotification),
98−) {
99− c.notifyMu.Lock()
100− defer c.notifyMu.Unlock()
101− c.notifications = append(c.notifications, handler)
102−}
103−
104−// readResponses continuously reads and processes responses from the server's stdout.
105−// It handles both responses to requests and notifications, routing them appropriately.
106−// Runs until the done channel is closed or an error occurs reading from stdout.
107−func (c *StdioMCPClient) readResponses() {
108− for {
109− select {
110− case <-c.done:
111− return
112− default:
113− line, err := c.stdout.ReadString('\n')
114− if err != nil {
115− if err != io.EOF {
116− fmt.Printf("Error reading response: %v\n", err)
117− }
118− return
119− }
120−
121− var baseMessage struct {
122− JSONRPC string `json:"jsonrpc"`
123− ID *int64 `json:"id,omitempty"`
124− Method string `json:"method,omitempty"`
125− Result json.RawMessage `json:"result,omitempty"`
126− Error *struct {
127− Code int `json:"code"`
128− Message string `json:"message"`
129− } `json:"error,omitempty"`
130− }
131
28
132− if err := json.Unmarshal([]byte(line), &baseMessage); err != nil {
29+ return NewClient(stdioTransport), nil
133− continue
134− }
135−
136− // Handle notification
137− if baseMessage.ID == nil {
138− var notification mcp.JSONRPCNotification
139− if err := json.Unmarshal([]byte(line), &notification); err != nil {
140− continue
141− }
142− c.notifyMu.RLock()
143− for _, handler := range c.notifications {
144− handler(notification)
145− }
146− c.notifyMu.RUnlock()
147− continue
148− }
149−
150− c.mu.RLock()
151− ch, ok := c.responses[*baseMessage.ID]
152− c.mu.RUnlock()
153−
154− if ok {
155− if baseMessage.Error != nil {
156− ch <- RPCResponse{
157− Error: &baseMessage.Error.Message,
158− }
159− } else {
160− ch <- RPCResponse{
161− Response: &baseMessage.Result,
162− }
163− }
164− c.mu.Lock()
165− delete(c.responses, *baseMessage.ID)
166− c.mu.Unlock()
167− }
168− }
169− }
170}
30}
171
31
172−// sendRequest sends a JSON-RPC request to the server and waits for a response.
32+// GetStderr returns a reader for the stderr output of the subprocess.
173−// It creates a unique request ID, sends the request over stdin, and waits for
33+// This can be used to capture error messages or logs from the subprocess.
174−// the corresponding response or context cancellation.
34+func GetStderr(c *Client) (io.Reader, bool) {
175−// Returns the raw JSON response message or an error if the request fails.
35+ t := c.GetTransport()
176−func (c *StdioMCPClient) sendRequest(
177− ctx context.Context,
178− method string,
179− params interface{},
180−) (*json.RawMessage, error) {
181− if !c.initialized && method != "initialize" {
182− return nil, fmt.Errorf("client not initialized")
183− }
184−
185− id := c.requestID.Add(1)
186−
187− // Create the complete request structure
188− request := mcp.JSONRPCRequest{
189− JSONRPC: mcp.JSONRPC_VERSION,
190− ID: id,
191− Request: mcp.Request{
192− Method: method,
193− },
194− Params: params,
195− }
196−
197− responseChan := make(chan RPCResponse, 1)
198− c.mu.Lock()
199− c.responses[id] = responseChan
200− c.mu.Unlock()
201−
202− requestBytes, err := json.Marshal(request)
203− if err != nil {
204− return nil, fmt.Errorf("failed to marshal request: %w", err)
205− }
206− requestBytes = append(requestBytes, '\n')
207−
208− if _, err := c.stdin.Write(requestBytes); err != nil {
209− return nil, fmt.Errorf("failed to write request: %w", err)
210− }
211−
212− select {
213− case <-ctx.Done():
214− c.mu.Lock()
215− delete(c.responses, id)
216− c.mu.Unlock()
217− return nil, ctx.Err()
218− case response := <-responseChan:
219− if response.Error != nil {
220− return nil, errors.New(*response.Error)
221− }
222− return response.Response, nil
223− }
224−}
225−
226−func (c *StdioMCPClient) Ping(ctx context.Context) error {
227− _, err := c.sendRequest(ctx, "ping", nil)
228− return err
229−}
230−
231−func (c *StdioMCPClient) Initialize(
232− ctx context.Context,
233− request mcp.InitializeRequest,
234−) (*mcp.InitializeResult, error) {
235− // This structure ensures Capabilities is always included in JSON
236− params := struct {
237− ProtocolVersion string `json:"protocolVersion"`
238− ClientInfo mcp.Implementation `json:"clientInfo"`
239− Capabilities mcp.ClientCapabilities `json:"capabilities"`
240− }{
241− ProtocolVersion: request.Params.ProtocolVersion,
242− ClientInfo: request.Params.ClientInfo,
243− Capabilities: request.Params.Capabilities, // Will be empty struct if not set
244− }
245−
246− response, err := c.sendRequest(ctx, "initialize", params)
247− if err != nil {
248− return nil, err
249− }
250−
251− var result mcp.InitializeResult
252− if err := json.Unmarshal(*response, &result); err != nil {
253− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
254− }
255−
256− // Store capabilities
257− c.capabilities = result.Capabilities
258−
259− // Send initialized notification
260− notification := mcp.JSONRPCNotification{
261− JSONRPC: mcp.JSONRPC_VERSION,
262− Notification: mcp.Notification{
263− Method: "notifications/initialized",
264− },
265− }
266−
267− notificationBytes, err := json.Marshal(notification)
268− if err != nil {
269− return nil, fmt.Errorf(
270− "failed to marshal initialized notification: %w",
271− err,
272− )
273− }
274− notificationBytes = append(notificationBytes, '\n')
275−
276− if _, err := c.stdin.Write(notificationBytes); err != nil {
277− return nil, fmt.Errorf(
278− "failed to send initialized notification: %w",
279− err,
280− )
281− }
282−
283− c.initialized = true
284− return &result, nil
285−}
286−
287−func (c *StdioMCPClient) ListResources(
288− ctx context.Context,
289− request mcp.ListResourcesRequest,
290−) (*mcp.
291− ListResourcesResult, error) {
292− response, err := c.sendRequest(
293− ctx,
294− "resources/list",
295− request.Params,
296− )
297− if err != nil {
298− return nil, err
299− }
300−
301− var result mcp.ListResourcesResult
302− if err := json.Unmarshal(*response, &result); err != nil {
303− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
304− }
305−
306− return &result, nil
307−}
308−
309−func (c *StdioMCPClient) ListResourceTemplates(
310− ctx context.Context,
311− request mcp.ListResourceTemplatesRequest,
312−) (*mcp.
313− ListResourceTemplatesResult, error) {
314− response, err := c.sendRequest(
315− ctx,
316− "resources/templates/list",
317− request.Params,
318− )
319− if err != nil {
320− return nil, err
321− }
322−
323− var result mcp.ListResourceTemplatesResult
324− if err := json.Unmarshal(*response, &result); err != nil {
325− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
326− }
327−
328− return &result, nil
329−}
330−
331−func (c *StdioMCPClient) ReadResource(
332− ctx context.Context,
333− request mcp.ReadResourceRequest,
334−) (*mcp.ReadResourceResult,
335− error) {
336− response, err := c.sendRequest(ctx, "resources/read", request.Params)
337− if err != nil {
338− return nil, err
339− }
340−
341− return mcp.ParseReadResourceResult(response)
342−}
343−
344−func (c *StdioMCPClient) Subscribe(
345− ctx context.Context,
346− request mcp.SubscribeRequest,
347−) error {
348− _, err := c.sendRequest(ctx, "resources/subscribe", request.Params)
349− return err
350−}
351−
352−func (c *StdioMCPClient) Unsubscribe(
353− ctx context.Context,
354− request mcp.UnsubscribeRequest,
355−) error {
356− _, err := c.sendRequest(ctx, "resources/unsubscribe", request.Params)
357− return err
358−}
359−
360−func (c *StdioMCPClient) ListPrompts(
361− ctx context.Context,
362− request mcp.ListPromptsRequest,
363−) (*mcp.ListPromptsResult, error) {
364− response, err := c.sendRequest(ctx, "prompts/list", request.Params)
365− if err != nil {
366− return nil, err
367− }
368−
369− var result mcp.ListPromptsResult
370− if err := json.Unmarshal(*response, &result); err != nil {
371− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
372− }
373−
374− return &result, nil
375−}
376−
377−func (c *StdioMCPClient) GetPrompt(
378− ctx context.Context,
379− request mcp.GetPromptRequest,
380−) (*mcp.GetPromptResult, error) {
381− response, err := c.sendRequest(ctx, "prompts/get", request.Params)
382− if err != nil {
383− return nil, err
384− }
385−
386− return mcp.ParseGetPromptResult(response)
387−}
388−
389−func (c *StdioMCPClient) ListTools(
390− ctx context.Context,
391− request mcp.ListToolsRequest,
392−) (*mcp.ListToolsResult, error) {
393− response, err := c.sendRequest(ctx, "tools/list", request.Params)
394− if err != nil {
395− return nil, err
396− }
397−
398− var result mcp.ListToolsResult
399− if err := json.Unmarshal(*response, &result); err != nil {
400− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
401− }
402−
403− return &result, nil
404−}
405−
406−func (c *StdioMCPClient) CallTool(
407− ctx context.Context,
408− request mcp.CallToolRequest,
409−) (*mcp.CallToolResult, error) {
410− response, err := c.sendRequest(ctx, "tools/call", request.Params)
411− if err != nil {
412− return nil, err
413− }
414−
415− return mcp.ParseCallToolResult(response)
416−}
417−
418−func (c *StdioMCPClient) SetLevel(
419− ctx context.Context,
420− request mcp.SetLevelRequest,
421−) error {
422− _, err := c.sendRequest(ctx, "logging/setLevel", request.Params)
423− return err
424−}
425−
426−func (c *StdioMCPClient) Complete(
427− ctx context.Context,
428− request mcp.CompleteRequest,
429−) (*mcp.CompleteResult, error) {
430− response, err := c.sendRequest(ctx, "completion/complete", request.Params)
431− if err != nil {
432− return nil, err
433− }
434
36
435− var result mcp.CompleteResult
37+ stdio, ok := t.(*transport.Stdio)
436− if err := json.Unmarshal(*response, &result); err != nil {
38+ if !ok {
437− return nil, fmt.Errorf("failed to unmarshal response: %w", err)
39+ return nil, false
438 }
40 }
439
41
440− return &result, nil
42+ return stdio.Stderr(), true
441}
43}
vendor/github.com/mark3labs/mcp-go/client/transport/inprocess.gonew file+70
@@ -0,0 +1,70 @@
1+package transport
2+
3+import (
4+ "context"
5+ "encoding/json"
6+ "fmt"
7+ "sync"
8+
9+ "github.com/mark3labs/mcp-go/mcp"
10+ "github.com/mark3labs/mcp-go/server"
11+)
12+
13+type InProcessTransport struct {
14+ server *server.MCPServer
15+
16+ onNotification func(mcp.JSONRPCNotification)
17+ notifyMu sync.RWMutex
18+}
19+
20+func NewInProcessTransport(server *server.MCPServer) *InProcessTransport {
21+ return &InProcessTransport{
22+ server: server,
23+ }
24+}
25+
26+func (c *InProcessTransport) Start(ctx context.Context) error {
27+ return nil
28+}
29+
30+func (c *InProcessTransport) SendRequest(ctx context.Context, request JSONRPCRequest) (*JSONRPCResponse, error) {
31+ requestBytes, err := json.Marshal(request)
32+ if err != nil {
33+ return nil, fmt.Errorf("failed to marshal request: %w", err)
34+ }
35+ requestBytes = append(requestBytes, '\n')
36+
37+ respMessage := c.server.HandleMessage(ctx, requestBytes)
38+ respByte, err := json.Marshal(respMessage)
39+ if err != nil {
40+ return nil, fmt.Errorf("failed to marshal response message: %w", err)
41+ }
42+ rpcResp := JSONRPCResponse{}
43+ err = json.Unmarshal(respByte, &rpcResp)
44+ if err != nil {
45+ return nil, fmt.Errorf("failed to unmarshal response message: %w", err)
46+ }
47+
48+ return &rpcResp, nil
49+}
50+
51+func (c *InProcessTransport) SendNotification(ctx context.Context, notification mcp.JSONRPCNotification) error {
52+ notificationBytes, err := json.Marshal(notification)
53+ if err != nil {
54+ return fmt.Errorf("failed to marshal notification: %w", err)
55+ }
56+ notificationBytes = append(notificationBytes, '\n')
57+ c.server.HandleMessage(ctx, notificationBytes)
58+
59+ return nil
60+}
61+
62+func (c *InProcessTransport) SetNotificationHandler(handler func(notification mcp.JSONRPCNotification)) {
63+ c.notifyMu.Lock()
64+ defer c.notifyMu.Unlock()
65+ c.onNotification = handler
66+}
67+
68+func (*InProcessTransport) Close() error {
69+ return nil
70+}
vendor/github.com/mark3labs/mcp-go/client/transport/interface.gonew file+50
@@ -0,0 +1,50 @@
1+package transport
2+
3+import (
4+ "context"
5+ "encoding/json"
6+
7+ "github.com/mark3labs/mcp-go/mcp"
8+)
9+
10+// HTTPHeaderFunc is a function that extracts header entries from the given context
11+// and returns them as key-value pairs. This is typically used to add context values
12+// as HTTP headers in outgoing requests.
13+type HTTPHeaderFunc func(context.Context) map[string]string
14+
15+// Interface for the transport layer.
16+type Interface interface {
17+ // Start the connection. Start should only be called once.
18+ Start(ctx context.Context) error
19+
20+ // SendRequest sends a json RPC request and returns the response synchronously.
21+ SendRequest(ctx context.Context, request JSONRPCRequest) (*JSONRPCResponse, error)
22+
23+ // SendNotification sends a json RPC Notification to the server.
24+ SendNotification(ctx context.Context, notification mcp.JSONRPCNotification) error
25+
26+ // SetNotificationHandler sets the handler for notifications.
27+ // Any notification before the handler is set will be discarded.
28+ SetNotificationHandler(handler func(notification mcp.JSONRPCNotification))
29+
30+ // Close the connection.
31+ Close() error
32+}
33+
34+type JSONRPCRequest struct {
35+ JSONRPC string `json:"jsonrpc"`
36+ ID mcp.RequestId `json:"id"`
37+ Method string `json:"method"`
38+ Params any `json:"params,omitempty"`
39+}
40+
41+type JSONRPCResponse struct {
42+ JSONRPC string `json:"jsonrpc"`
43+ ID mcp.RequestId `json:"id"`
44+ Result json.RawMessage `json:"result"`
45+ Error *struct {
46+ Code int `json:"code"`
47+ Message string `json:"message"`
48+ Data json.RawMessage `json:"data"`
49+ } `json:"error"`
50+}
vendor/github.com/mark3labs/mcp-go/client/transport/oauth.gonew file+650
@@ -0,0 +1,650 @@
1+package transport
2+
3+import (
4+ "bytes"
5+ "context"
6+ "encoding/json"
7+ "errors"
8+ "fmt"
9+ "io"
10+ "net/http"
11+ "net/url"
12+ "strings"
13+ "sync"
14+ "time"
15+)
16+
17+// OAuthConfig holds the OAuth configuration for the client
18+type OAuthConfig struct {
19+ // ClientID is the OAuth client ID
20+ ClientID string
21+ // ClientSecret is the OAuth client secret (for confidential clients)
22+ ClientSecret string
23+ // RedirectURI is the redirect URI for the OAuth flow
24+ RedirectURI string
25+ // Scopes is the list of OAuth scopes to request
26+ Scopes []string
27+ // TokenStore is the storage for OAuth tokens
28+ TokenStore TokenStore
29+ // AuthServerMetadataURL is the URL to the OAuth server metadata
30+ // If empty, the client will attempt to discover it from the base URL
31+ AuthServerMetadataURL string
32+ // PKCEEnabled enables PKCE for the OAuth flow (recommended for public clients)
33+ PKCEEnabled bool
34+}
35+
36+// TokenStore is an interface for storing and retrieving OAuth tokens
37+type TokenStore interface {
38+ // GetToken returns the current token
39+ GetToken() (*Token, error)
40+ // SaveToken saves a token
41+ SaveToken(token *Token) error
42+}
43+
44+// Token represents an OAuth token
45+type Token struct {
46+ // AccessToken is the OAuth access token
47+ AccessToken string `json:"access_token"`
48+ // TokenType is the type of token (usually "Bearer")
49+ TokenType string `json:"token_type"`
50+ // RefreshToken is the OAuth refresh token
51+ RefreshToken string `json:"refresh_token,omitempty"`
52+ // ExpiresIn is the number of seconds until the token expires
53+ ExpiresIn int64 `json:"expires_in,omitempty"`
54+ // Scope is the scope of the token
55+ Scope string `json:"scope,omitempty"`
56+ // ExpiresAt is the time when the token expires
57+ ExpiresAt time.Time `json:"expires_at,omitempty"`
58+}
59+
60+// IsExpired returns true if the token is expired
61+func (t *Token) IsExpired() bool {
62+ if t.ExpiresAt.IsZero() {
63+ return false
64+ }
65+ return time.Now().After(t.ExpiresAt)
66+}
67+
68+// MemoryTokenStore is a simple in-memory token store
69+type MemoryTokenStore struct {
70+ token *Token
71+ mu sync.RWMutex
72+}
73+
74+// NewMemoryTokenStore creates a new in-memory token store
75+func NewMemoryTokenStore() *MemoryTokenStore {
76+ return &MemoryTokenStore{}
77+}
78+
79+// GetToken returns the current token
80+func (s *MemoryTokenStore) GetToken() (*Token, error) {
81+ s.mu.RLock()
82+ defer s.mu.RUnlock()
83+ if s.token == nil {
84+ return nil, errors.New("no token available")
85+ }
86+ return s.token, nil
87+}
88+
89+// SaveToken saves a token
90+func (s *MemoryTokenStore) SaveToken(token *Token) error {
91+ s.mu.Lock()
92+ defer s.mu.Unlock()
93+ s.token = token
94+ return nil
95+}
96+
97+// AuthServerMetadata represents the OAuth 2.0 Authorization Server Metadata
98+type AuthServerMetadata struct {
99+ Issuer string `json:"issuer"`
100+ AuthorizationEndpoint string `json:"authorization_endpoint"`
101+ TokenEndpoint string `json:"token_endpoint"`
102+ RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
103+ JwksURI string `json:"jwks_uri,omitempty"`
104+ ScopesSupported []string `json:"scopes_supported,omitempty"`
105+ ResponseTypesSupported []string `json:"response_types_supported"`
106+ GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
107+ TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`
108+}
109+
110+// OAuthHandler handles OAuth authentication for HTTP requests
111+type OAuthHandler struct {
112+ config OAuthConfig
113+ httpClient *http.Client
114+ serverMetadata *AuthServerMetadata
115+ metadataFetchErr error
116+ metadataOnce sync.Once
117+ baseURL string
118+ expectedState string // Expected state value for CSRF protection
119+}
120+
121+// NewOAuthHandler creates a new OAuth handler
122+func NewOAuthHandler(config OAuthConfig) *OAuthHandler {
123+ if config.TokenStore == nil {
124+ config.TokenStore = NewMemoryTokenStore()
125+ }
126+
127+ return &OAuthHandler{
128+ config: config,
129+ httpClient: &http.Client{Timeout: 30 * time.Second},
130+ }
131+}
132+
133+// GetAuthorizationHeader returns the Authorization header value for a request
134+func (h *OAuthHandler) GetAuthorizationHeader(ctx context.Context) (string, error) {
135+ token, err := h.getValidToken(ctx)
136+ if err != nil {
137+ return "", err
138+ }
139+
140+ // Some auth implementations are strict about token type
141+ tokenType := token.TokenType
142+ if tokenType == "bearer" {
143+ tokenType = "Bearer"
144+ }
145+
146+ return fmt.Sprintf("%s %s", tokenType, token.AccessToken), nil
147+}
148+
149+// getValidToken returns a valid token, refreshing if necessary
150+func (h *OAuthHandler) getValidToken(ctx context.Context) (*Token, error) {
151+ token, err := h.config.TokenStore.GetToken()
152+ if err == nil && !token.IsExpired() && token.AccessToken != "" {
153+ return token, nil
154+ }
155+
156+ // If we have a refresh token, try to use it
157+ if err == nil && token.RefreshToken != "" {
158+ newToken, err := h.refreshToken(ctx, token.RefreshToken)
159+ if err == nil {
160+ return newToken, nil
161+ }
162+ // If refresh fails, continue to authorization flow
163+ }
164+
165+ // We need to get a new token through the authorization flow
166+ return nil, ErrOAuthAuthorizationRequired
167+}
168+
169+// refreshToken refreshes an OAuth token
170+func (h *OAuthHandler) refreshToken(ctx context.Context, refreshToken string) (*Token, error) {
171+ metadata, err := h.getServerMetadata(ctx)
172+ if err != nil {
173+ return nil, fmt.Errorf("failed to get server metadata: %w", err)
174+ }
175+
176+ data := url.Values{}
177+ data.Set("grant_type", "refresh_token")
178+ data.Set("refresh_token", refreshToken)
179+ data.Set("client_id", h.config.ClientID)
180+ if h.config.ClientSecret != "" {
181+ data.Set("client_secret", h.config.ClientSecret)
182+ }
183+
184+ req, err := http.NewRequestWithContext(
185+ ctx,
186+ http.MethodPost,
187+ metadata.TokenEndpoint,
188+ strings.NewReader(data.Encode()),
189+ )
190+ if err != nil {
191+ return nil, fmt.Errorf("failed to create refresh token request: %w", err)
192+ }
193+
194+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
195+ req.Header.Set("Accept", "application/json")
196+
197+ resp, err := h.httpClient.Do(req)
198+ if err != nil {
199+ return nil, fmt.Errorf("failed to send refresh token request: %w", err)
200+ }
201+ defer resp.Body.Close()
202+
203+ if resp.StatusCode != http.StatusOK {
204+ body, _ := io.ReadAll(resp.Body)
205+ return nil, extractOAuthError(body, resp.StatusCode, "refresh token request failed")
206+ }
207+
208+ var tokenResp Token
209+ if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
210+ return nil, fmt.Errorf("failed to decode token response: %w", err)
211+ }
212+
213+ // Set expiration time
214+ if tokenResp.ExpiresIn > 0 {
215+ tokenResp.ExpiresAt = time.Now().Add(time.Duration(tokenResp.ExpiresIn) * time.Second)
216+ }
217+
218+ // If no new refresh token is provided, keep the old one
219+ oldToken, _ := h.config.TokenStore.GetToken()
220+ if tokenResp.RefreshToken == "" && oldToken != nil {
221+ tokenResp.RefreshToken = oldToken.RefreshToken
222+ }
223+
224+ // Save the token
225+ if err := h.config.TokenStore.SaveToken(&tokenResp); err != nil {
226+ return nil, fmt.Errorf("failed to save token: %w", err)
227+ }
228+
229+ return &tokenResp, nil
230+}
231+
232+// RefreshToken is a public wrapper for refreshToken
233+func (h *OAuthHandler) RefreshToken(ctx context.Context, refreshToken string) (*Token, error) {
234+ return h.refreshToken(ctx, refreshToken)
235+}
236+
237+// GetClientID returns the client ID
238+func (h *OAuthHandler) GetClientID() string {
239+ return h.config.ClientID
240+}
241+
242+// extractOAuthError attempts to parse an OAuth error response from the response body
243+func extractOAuthError(body []byte, statusCode int, context string) error {
244+ // Try to parse the error as an OAuth error response
245+ var oauthErr OAuthError
246+ if err := json.Unmarshal(body, &oauthErr); err == nil && oauthErr.ErrorCode != "" {
247+ return fmt.Errorf("%s: %w", context, oauthErr)
248+ }
249+
250+ // If not a valid OAuth error, return the raw response
251+ return fmt.Errorf("%s with status %d: %s", context, statusCode, body)
252+}
253+
254+// GetClientSecret returns the client secret
255+func (h *OAuthHandler) GetClientSecret() string {
256+ return h.config.ClientSecret
257+}
258+
259+// SetBaseURL sets the base URL for the API server
260+func (h *OAuthHandler) SetBaseURL(baseURL string) {
261+ h.baseURL = baseURL
262+}
263+
264+// GetExpectedState returns the expected state value (for testing purposes)
265+func (h *OAuthHandler) GetExpectedState() string {
266+ return h.expectedState
267+}
268+
269+// OAuthError represents a standard OAuth 2.0 error response
270+type OAuthError struct {
271+ ErrorCode string `json:"error"`
272+ ErrorDescription string `json:"error_description,omitempty"`
273+ ErrorURI string `json:"error_uri,omitempty"`
274+}
275+
276+// Error implements the error interface
277+func (e OAuthError) Error() string {
278+ if e.ErrorDescription != "" {
279+ return fmt.Sprintf("OAuth error: %s - %s", e.ErrorCode, e.ErrorDescription)
280+ }
281+ return fmt.Sprintf("OAuth error: %s", e.ErrorCode)
282+}
283+
284+// OAuthProtectedResource represents the response from /.well-known/oauth-protected-resource
285+type OAuthProtectedResource struct {
286+ AuthorizationServers []string `json:"authorization_servers"`
287+ Resource string `json:"resource"`
288+ ResourceName string `json:"resource_name,omitempty"`
289+}
290+
291+// getServerMetadata fetches the OAuth server metadata
292+func (h *OAuthHandler) getServerMetadata(ctx context.Context) (*AuthServerMetadata, error) {
293+ h.metadataOnce.Do(func() {
294+ // If AuthServerMetadataURL is explicitly provided, use it directly
295+ if h.config.AuthServerMetadataURL != "" {
296+ h.fetchMetadataFromURL(ctx, h.config.AuthServerMetadataURL)
297+ return
298+ }
299+
300+ // Try to discover the authorization server via OAuth Protected Resource
301+ // as per RFC 9728 (https://datatracker.ietf.org/doc/html/rfc9728)
302+ baseURL, err := h.extractBaseURL()
303+ if err != nil {
304+ h.metadataFetchErr = fmt.Errorf("failed to extract base URL: %w", err)
305+ return
306+ }
307+
308+ // Try to fetch the OAuth Protected Resource metadata
309+ protectedResourceURL := baseURL + "/.well-known/oauth-protected-resource"
310+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, protectedResourceURL, nil)
311+ if err != nil {
312+ h.metadataFetchErr = fmt.Errorf("failed to create protected resource request: %w", err)
313+ return
314+ }
315+
316+ req.Header.Set("Accept", "application/json")
317+ req.Header.Set("MCP-Protocol-Version", "2025-03-26")
318+
319+ resp, err := h.httpClient.Do(req)
320+ if err != nil {
321+ h.metadataFetchErr = fmt.Errorf("failed to send protected resource request: %w", err)
322+ return
323+ }
324+ defer resp.Body.Close()
325+
326+ // If we can't get the protected resource metadata, fall back to default endpoints
327+ if resp.StatusCode != http.StatusOK {
328+ metadata, err := h.getDefaultEndpoints(baseURL)
329+ if err != nil {
330+ h.metadataFetchErr = fmt.Errorf("failed to get default endpoints: %w", err)
331+ return
332+ }
333+ h.serverMetadata = metadata
334+ return
335+ }
336+
337+ // Parse the protected resource metadata
338+ var protectedResource OAuthProtectedResource
339+ if err := json.NewDecoder(resp.Body).Decode(&protectedResource); err != nil {
340+ h.metadataFetchErr = fmt.Errorf("failed to decode protected resource response: %w", err)
341+ return
342+ }
343+
344+ // If no authorization servers are specified, fall back to default endpoints
345+ if len(protectedResource.AuthorizationServers) == 0 {
346+ metadata, err := h.getDefaultEndpoints(baseURL)
347+ if err != nil {
348+ h.metadataFetchErr = fmt.Errorf("failed to get default endpoints: %w", err)
349+ return
350+ }
351+ h.serverMetadata = metadata
352+ return
353+ }
354+
355+ // Use the first authorization server
356+ authServerURL := protectedResource.AuthorizationServers[0]
357+
358+ // Try OpenID Connect discovery first
359+ h.fetchMetadataFromURL(ctx, authServerURL+"/.well-known/openid-configuration")
360+ if h.serverMetadata != nil {
361+ return
362+ }
363+
364+ // If OpenID Connect discovery fails, try OAuth Authorization Server Metadata
365+ h.fetchMetadataFromURL(ctx, authServerURL+"/.well-known/oauth-authorization-server")
366+ if h.serverMetadata != nil {
367+ return
368+ }
369+
370+ // If both discovery methods fail, use default endpoints based on the authorization server URL
371+ metadata, err := h.getDefaultEndpoints(authServerURL)
372+ if err != nil {
373+ h.metadataFetchErr = fmt.Errorf("failed to get default endpoints: %w", err)
374+ return
375+ }
376+ h.serverMetadata = metadata
377+ })
378+
379+ if h.metadataFetchErr != nil {
380+ return nil, h.metadataFetchErr
381+ }
382+
383+ return h.serverMetadata, nil
384+}
385+
386+// fetchMetadataFromURL fetches and parses OAuth server metadata from a URL
387+func (h *OAuthHandler) fetchMetadataFromURL(ctx context.Context, metadataURL string) {
388+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, metadataURL, nil)
389+ if err != nil {
390+ h.metadataFetchErr = fmt.Errorf("failed to create metadata request: %w", err)
391+ return
392+ }
393+
394+ req.Header.Set("Accept", "application/json")
395+ req.Header.Set("MCP-Protocol-Version", "2025-03-26")
396+
397+ resp, err := h.httpClient.Do(req)
398+ if err != nil {
399+ h.metadataFetchErr = fmt.Errorf("failed to send metadata request: %w", err)
400+ return
401+ }
402+ defer resp.Body.Close()
403+
404+ if resp.StatusCode != http.StatusOK {
405+ // If metadata discovery fails, don't set any metadata
406+ return
407+ }
408+
409+ var metadata AuthServerMetadata
410+ if err := json.NewDecoder(resp.Body).Decode(&metadata); err != nil {
411+ h.metadataFetchErr = fmt.Errorf("failed to decode metadata response: %w", err)
412+ return
413+ }
414+
415+ h.serverMetadata = &metadata
416+}
417+
418+// extractBaseURL extracts the base URL from the first request
419+func (h *OAuthHandler) extractBaseURL() (string, error) {
420+ // If we have a base URL from a previous request, use it
421+ if h.baseURL != "" {
422+ return h.baseURL, nil
423+ }
424+
425+ // Otherwise, we need to infer it from the redirect URI
426+ if h.config.RedirectURI == "" {
427+ return "", fmt.Errorf("no base URL available and no redirect URI provided")
428+ }
429+
430+ // Parse the redirect URI to extract the authority
431+ parsedURL, err := url.Parse(h.config.RedirectURI)
432+ if err != nil {
433+ return "", fmt.Errorf("failed to parse redirect URI: %w", err)
434+ }
435+
436+ // Use the scheme and host from the redirect URI
437+ baseURL := fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host)
438+ return baseURL, nil
439+}
440+
441+// GetServerMetadata is a public wrapper for getServerMetadata
442+func (h *OAuthHandler) GetServerMetadata(ctx context.Context) (*AuthServerMetadata, error) {
443+ return h.getServerMetadata(ctx)
444+}
445+
446+// getDefaultEndpoints returns default OAuth endpoints based on the base URL
447+func (h *OAuthHandler) getDefaultEndpoints(baseURL string) (*AuthServerMetadata, error) {
448+ // Parse the base URL to extract the authority
449+ parsedURL, err := url.Parse(baseURL)
450+ if err != nil {
451+ return nil, fmt.Errorf("failed to parse base URL: %w", err)
452+ }
453+
454+ // Discard any path component to get the authorization base URL
455+ parsedURL.Path = ""
456+ authBaseURL := parsedURL.String()
457+
458+ // Validate that the URL has a scheme and host
459+ if parsedURL.Scheme == "" || parsedURL.Host == "" {
460+ return nil, fmt.Errorf("invalid base URL: missing scheme or host in %q", baseURL)
461+ }
462+
463+ return &AuthServerMetadata{
464+ Issuer: authBaseURL,
465+ AuthorizationEndpoint: authBaseURL + "/authorize",
466+ TokenEndpoint: authBaseURL + "/token",
467+ RegistrationEndpoint: authBaseURL + "/register",
468+ }, nil
469+}
470+
471+// RegisterClient performs dynamic client registration
472+func (h *OAuthHandler) RegisterClient(ctx context.Context, clientName string) error {
473+ metadata, err := h.getServerMetadata(ctx)
474+ if err != nil {
475+ return fmt.Errorf("failed to get server metadata: %w", err)
476+ }
477+
478+ if metadata.RegistrationEndpoint == "" {
479+ return errors.New("server does not support dynamic client registration")
480+ }
481+
482+ // Prepare registration request
483+ regRequest := map[string]any{
484+ "client_name": clientName,
485+ "redirect_uris": []string{h.config.RedirectURI},
486+ "token_endpoint_auth_method": "none", // For public clients
487+ "grant_types": []string{"authorization_code", "refresh_token"},
488+ "response_types": []string{"code"},
489+ "scope": strings.Join(h.config.Scopes, " "),
490+ }
491+
492+ // Add client_secret if this is a confidential client
493+ if h.config.ClientSecret != "" {
494+ regRequest["token_endpoint_auth_method"] = "client_secret_basic"
495+ }
496+
497+ reqBody, err := json.Marshal(regRequest)
498+ if err != nil {
499+ return fmt.Errorf("failed to marshal registration request: %w", err)
500+ }
501+
502+ req, err := http.NewRequestWithContext(
503+ ctx,
504+ http.MethodPost,
505+ metadata.RegistrationEndpoint,
506+ bytes.NewReader(reqBody),
507+ )
508+ if err != nil {
509+ return fmt.Errorf("failed to create registration request: %w", err)
510+ }
511+
512+ req.Header.Set("Content-Type", "application/json")
513+ req.Header.Set("Accept", "application/json")
514+
515+ resp, err := h.httpClient.Do(req)
516+ if err != nil {
517+ return fmt.Errorf("failed to send registration request: %w", err)
518+ }
519+ defer resp.Body.Close()
520+
521+ if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
522+ body, _ := io.ReadAll(resp.Body)
523+ return extractOAuthError(body, resp.StatusCode, "registration request failed")
524+ }
525+
526+ var regResponse struct {
527+ ClientID string `json:"client_id"`
528+ ClientSecret string `json:"client_secret,omitempty"`
529+ }
530+
531+ if err := json.NewDecoder(resp.Body).Decode(&regResponse); err != nil {
532+ return fmt.Errorf("failed to decode registration response: %w", err)
533+ }
534+
535+ // Update the client configuration
536+ h.config.ClientID = regResponse.ClientID
537+ if regResponse.ClientSecret != "" {
538+ h.config.ClientSecret = regResponse.ClientSecret
539+ }
540+
541+ return nil
542+}
543+
544+// ErrInvalidState is returned when the state parameter doesn't match the expected value
545+var ErrInvalidState = errors.New("invalid state parameter, possible CSRF attack")
546+
547+// ProcessAuthorizationResponse processes the authorization response and exchanges the code for a token
548+func (h *OAuthHandler) ProcessAuthorizationResponse(ctx context.Context, code, state, codeVerifier string) error {
549+ // Validate the state parameter to prevent CSRF attacks
550+ if h.expectedState == "" {
551+ return errors.New("no expected state found, authorization flow may not have been initiated properly")
552+ }
553+
554+ if state != h.expectedState {
555+ return ErrInvalidState
556+ }
557+
558+ // Clear the expected state after validation
559+ defer func() {
560+ h.expectedState = ""
561+ }()
562+
563+ metadata, err := h.getServerMetadata(ctx)
564+ if err != nil {
565+ return fmt.Errorf("failed to get server metadata: %w", err)
566+ }
567+
568+ data := url.Values{}
569+ data.Set("grant_type", "authorization_code")
570+ data.Set("code", code)
571+ data.Set("client_id", h.config.ClientID)
572+ data.Set("redirect_uri", h.config.RedirectURI)
573+
574+ if h.config.ClientSecret != "" {
575+ data.Set("client_secret", h.config.ClientSecret)
576+ }
577+
578+ if h.config.PKCEEnabled && codeVerifier != "" {
579+ data.Set("code_verifier", codeVerifier)
580+ }
581+
582+ req, err := http.NewRequestWithContext(
583+ ctx,
584+ http.MethodPost,
585+ metadata.TokenEndpoint,
586+ strings.NewReader(data.Encode()),
587+ )
588+ if err != nil {
589+ return fmt.Errorf("failed to create token request: %w", err)
590+ }
591+
592+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
593+ req.Header.Set("Accept", "application/json")
594+
595+ resp, err := h.httpClient.Do(req)
596+ if err != nil {
597+ return fmt.Errorf("failed to send token request: %w", err)
598+ }
599+ defer resp.Body.Close()
600+
601+ if resp.StatusCode != http.StatusOK {
602+ body, _ := io.ReadAll(resp.Body)
603+ return extractOAuthError(body, resp.StatusCode, "token request failed")
604+ }
605+
606+ var tokenResp Token
607+ if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
608+ return fmt.Errorf("failed to decode token response: %w", err)
609+ }
610+
611+ // Set expiration time
612+ if tokenResp.ExpiresIn > 0 {
613+ tokenResp.ExpiresAt = time.Now().Add(time.Duration(tokenResp.ExpiresIn) * time.Second)
614+ }
615+
616+ // Save the token
617+ if err := h.config.TokenStore.SaveToken(&tokenResp); err != nil {
618+ return fmt.Errorf("failed to save token: %w", err)
619+ }
620+
621+ return nil
622+}
623+
624+// GetAuthorizationURL returns the URL for the authorization endpoint
625+func (h *OAuthHandler) GetAuthorizationURL(ctx context.Context, state, codeChallenge string) (string, error) {
626+ metadata, err := h.getServerMetadata(ctx)
627+ if err != nil {
628+ return "", fmt.Errorf("failed to get server metadata: %w", err)
629+ }
630+
631+ // Store the state for later validation
632+ h.expectedState = state
633+
634+ params := url.Values{}
635+ params.Set("response_type", "code")
636+ params.Set("client_id", h.config.ClientID)
637+ params.Set("redirect_uri", h.config.RedirectURI)
638+ params.Set("state", state)
639+
640+ if len(h.config.Scopes) > 0 {
641+ params.Set("scope", strings.Join(h.config.Scopes, " "))
642+ }
643+
644+ if h.config.PKCEEnabled && codeChallenge != "" {
645+ params.Set("code_challenge", codeChallenge)
646+ params.Set("code_challenge_method", "S256")
647+ }
648+
649+ return metadata.AuthorizationEndpoint + "?" + params.Encode(), nil
650+}
vendor/github.com/mark3labs/mcp-go/client/transport/oauth_utils.gonew file+68
@@ -0,0 +1,68 @@
1+package transport
2+
3+import (
4+ "crypto/rand"
5+ "crypto/sha256"
6+ "encoding/base64"
7+ "fmt"
8+ "net/url"
9+)
10+
11+// GenerateRandomString generates a random string of the specified length
12+func GenerateRandomString(length int) (string, error) {
13+ bytes := make([]byte, length)
14+ if _, err := rand.Read(bytes); err != nil {
15+ return "", err
16+ }
17+ return base64.RawURLEncoding.EncodeToString(bytes)[:length], nil
18+}
19+
20+// GenerateCodeVerifier generates a code verifier for PKCE
21+func GenerateCodeVerifier() (string, error) {
22+ // According to RFC 7636, the code verifier should be between 43 and 128 characters
23+ return GenerateRandomString(64)
24+}
25+
26+// GenerateCodeChallenge generates a code challenge from a code verifier
27+func GenerateCodeChallenge(codeVerifier string) string {
28+ // SHA256 hash the code verifier
29+ hash := sha256.Sum256([]byte(codeVerifier))
30+ // Base64url encode the hash
31+ return base64.RawURLEncoding.EncodeToString(hash[:])
32+}
33+
34+// GenerateState generates a state parameter for OAuth
35+func GenerateState() (string, error) {
36+ return GenerateRandomString(32)
37+}
38+
39+// ValidateRedirectURI validates that a redirect URI is secure
40+func ValidateRedirectURI(redirectURI string) error {
41+ // According to the spec, redirect URIs must be either localhost URLs or HTTPS URLs
42+ if redirectURI == "" {
43+ return fmt.Errorf("redirect URI cannot be empty")
44+ }
45+
46+ // Parse the URL
47+ parsedURL, err := url.Parse(redirectURI)
48+ if err != nil {
49+ return fmt.Errorf("invalid redirect URI: %w", err)
50+ }
51+
52+ // Check if it's a localhost URL
53+ if parsedURL.Scheme == "http" {
54+ hostname := parsedURL.Hostname()
55+ // Check for various forms of localhost
56+ if hostname == "localhost" || hostname == "127.0.0.1" || hostname == "::1" || hostname == "[::1]" {
57+ return nil
58+ }
59+ return fmt.Errorf("HTTP redirect URI must use localhost or 127.0.0.1")
60+ }
61+
62+ // Check if it's an HTTPS URL
63+ if parsedURL.Scheme == "https" {
64+ return nil
65+ }
66+
67+ return fmt.Errorf("redirect URI must use either HTTP with localhost or HTTPS")
68+}
vendor/github.com/mark3labs/mcp-go/client/transport/sse.gonew file+522
@@ -0,0 +1,522 @@
1+package transport
2+
3+import (
4+ "bufio"
5+ "bytes"
6+ "context"
7+ "encoding/json"
8+ "errors"
9+ "fmt"
10+ "io"
11+ "net/http"
12+ "net/url"
13+ "strings"
14+ "sync"
15+ "sync/atomic"
16+ "time"
17+
18+ "github.com/mark3labs/mcp-go/mcp"
19+)
20+
21+// SSE implements the transport layer of the MCP protocol using Server-Sent Events (SSE).
22+// It maintains a persistent HTTP connection to receive server-pushed events
23+// while sending requests over regular HTTP POST calls. The client handles
24+// automatic reconnection and message routing between requests and responses.
25+type SSE struct {
26+ baseURL *url.URL
27+ endpoint *url.URL
28+ httpClient *http.Client
29+ responses map[string]chan *JSONRPCResponse
30+ mu sync.RWMutex
31+ onNotification func(mcp.JSONRPCNotification)
32+ notifyMu sync.RWMutex
33+ endpointChan chan struct{}
34+ headers map[string]string
35+ headerFunc HTTPHeaderFunc
36+
37+ started atomic.Bool
38+ closed atomic.Bool
39+ cancelSSEStream context.CancelFunc
40+
41+ // OAuth support
42+ oauthHandler *OAuthHandler
43+}
44+
45+type ClientOption func(*SSE)
46+
47+func WithHeaders(headers map[string]string) ClientOption {
48+ return func(sc *SSE) {
49+ sc.headers = headers
50+ }
51+}
52+
53+func WithHeaderFunc(headerFunc HTTPHeaderFunc) ClientOption {
54+ return func(sc *SSE) {
55+ sc.headerFunc = headerFunc
56+ }
57+}
58+
59+func WithHTTPClient(httpClient *http.Client) ClientOption {
60+ return func(sc *SSE) {
61+ sc.httpClient = httpClient
62+ }
63+}
64+
65+func WithOAuth(config OAuthConfig) ClientOption {
66+ return func(sc *SSE) {
67+ sc.oauthHandler = NewOAuthHandler(config)
68+ }
69+}
70+
71+// NewSSE creates a new SSE-based MCP client with the given base URL.
72+// Returns an error if the URL is invalid.
73+func NewSSE(baseURL string, options ...ClientOption) (*SSE, error) {
74+ parsedURL, err := url.Parse(baseURL)
75+ if err != nil {
76+ return nil, fmt.Errorf("invalid URL: %w", err)
77+ }
78+
79+ smc := &SSE{
80+ baseURL: parsedURL,
81+ httpClient: &http.Client{},
82+ responses: make(map[string]chan *JSONRPCResponse),
83+ endpointChan: make(chan struct{}),
84+ headers: make(map[string]string),
85+ }
86+
87+ for _, opt := range options {
88+ opt(smc)
89+ }
90+
91+ // If OAuth is configured, set the base URL for metadata discovery
92+ if smc.oauthHandler != nil {
93+ // Extract base URL from server URL for metadata discovery
94+ baseURL := fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host)
95+ smc.oauthHandler.SetBaseURL(baseURL)
96+ }
97+
98+ return smc, nil
99+}
100+
101+// Start initiates the SSE connection to the server and waits for the endpoint information.
102+// Returns an error if the connection fails or times out waiting for the endpoint.
103+func (c *SSE) Start(ctx context.Context) error {
104+
105+ if c.started.Load() {
106+ return fmt.Errorf("has already started")
107+ }
108+
109+ ctx, cancel := context.WithCancel(ctx)
110+ c.cancelSSEStream = cancel
111+
112+ req, err := http.NewRequestWithContext(ctx, "GET", c.baseURL.String(), nil)
113+
114+ if err != nil {
115+ return fmt.Errorf("failed to create request: %w", err)
116+ }
117+
118+ req.Header.Set("Accept", "text/event-stream")
119+ req.Header.Set("Cache-Control", "no-cache")
120+ req.Header.Set("Connection", "keep-alive")
121+
122+ // set custom http headers
123+ for k, v := range c.headers {
124+ req.Header.Set(k, v)
125+ }
126+ if c.headerFunc != nil {
127+ for k, v := range c.headerFunc(ctx) {
128+ req.Header.Set(k, v)
129+ }
130+ }
131+
132+ // Add OAuth authorization if configured
133+ if c.oauthHandler != nil {
134+ authHeader, err := c.oauthHandler.GetAuthorizationHeader(ctx)
135+ if err != nil {
136+ // If we get an authorization error, return a specific error that can be handled by the client
137+ if err.Error() == "no valid token available, authorization required" {
138+ return &OAuthAuthorizationRequiredError{
139+ Handler: c.oauthHandler,
140+ }
141+ }
142+ return fmt.Errorf("failed to get authorization header: %w", err)
143+ }
144+ req.Header.Set("Authorization", authHeader)
145+ }
146+
147+ resp, err := c.httpClient.Do(req)
148+ if err != nil {
149+ return fmt.Errorf("failed to connect to SSE stream: %w", err)
150+ }
151+
152+ if resp.StatusCode != http.StatusOK {
153+ resp.Body.Close()
154+ // Handle OAuth unauthorized error
155+ if resp.StatusCode == http.StatusUnauthorized && c.oauthHandler != nil {
156+ return &OAuthAuthorizationRequiredError{
157+ Handler: c.oauthHandler,
158+ }
159+ }
160+ return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
161+ }
162+
163+ go c.readSSE(resp.Body)
164+
165+ // Wait for the endpoint to be received
166+ timeout := time.NewTimer(30 * time.Second)
167+ defer timeout.Stop()
168+ select {
169+ case <-c.endpointChan:
170+ // Endpoint received, proceed
171+ case <-ctx.Done():
172+ return fmt.Errorf("context cancelled while waiting for endpoint")
173+ case <-timeout.C: // Add a timeout
174+ cancel()
175+ return fmt.Errorf("timeout waiting for endpoint")
176+ }
177+
178+ c.started.Store(true)
179+ return nil
180+}
181+
182+// readSSE continuously reads the SSE stream and processes events.
183+// It runs until the connection is closed or an error occurs.
184+func (c *SSE) readSSE(reader io.ReadCloser) {
185+ defer reader.Close()
186+
187+ br := bufio.NewReader(reader)
188+ var event, data string
189+
190+ for {
191+ // when close or start's ctx cancel, the reader will be closed
192+ // and the for loop will break.
193+ line, err := br.ReadString('\n')
194+ if err != nil {
195+ if err == io.EOF {
196+ // Process any pending event before exit
197+ if data != "" {
198+ // If no event type is specified, use empty string (default event type)
199+ if event == "" {
200+ event = "message"
201+ }
202+ c.handleSSEEvent(event, data)
203+ }
204+ break
205+ }
206+ if !c.closed.Load() {
207+ fmt.Printf("SSE stream error: %v\n", err)
208+ }
209+ return
210+ }
211+
212+ // Remove only newline markers
213+ line = strings.TrimRight(line, "\r\n")
214+ if line == "" {
215+ // Empty line means end of event
216+ if data != "" {
217+ // If no event type is specified, use empty string (default event type)
218+ if event == "" {
219+ event = "message"
220+ }
221+ c.handleSSEEvent(event, data)
222+ event = ""
223+ data = ""
224+ }
225+ continue
226+ }
227+
228+ if strings.HasPrefix(line, "event:") {
229+ event = strings.TrimSpace(strings.TrimPrefix(line, "event:"))
230+ } else if strings.HasPrefix(line, "data:") {
231+ data = strings.TrimSpace(strings.TrimPrefix(line, "data:"))
232+ }
233+ }
234+}
235+
236+// handleSSEEvent processes SSE events based on their type.
237+// Handles 'endpoint' events for connection setup and 'message' events for JSON-RPC communication.
238+func (c *SSE) handleSSEEvent(event, data string) {
239+ switch event {
240+ case "endpoint":
241+ endpoint, err := c.baseURL.Parse(data)
242+ if err != nil {
243+ fmt.Printf("Error parsing endpoint URL: %v\n", err)
244+ return
245+ }
246+ if endpoint.Host != c.baseURL.Host {
247+ fmt.Printf("Endpoint origin does not match connection origin\n")
248+ return
249+ }
250+ c.endpoint = endpoint
251+ close(c.endpointChan)
252+
253+ case "message":
254+ var baseMessage JSONRPCResponse
255+ if err := json.Unmarshal([]byte(data), &baseMessage); err != nil {
256+ fmt.Printf("Error unmarshaling message: %v\n", err)
257+ return
258+ }
259+
260+ // Handle notification
261+ if baseMessage.ID.IsNil() {
262+ var notification mcp.JSONRPCNotification
263+ if err := json.Unmarshal([]byte(data), &notification); err != nil {
264+ return
265+ }
266+ c.notifyMu.RLock()
267+ if c.onNotification != nil {
268+ c.onNotification(notification)
269+ }
270+ c.notifyMu.RUnlock()
271+ return
272+ }
273+
274+ // Create string key for map lookup
275+ idKey := baseMessage.ID.String()
276+
277+ c.mu.RLock()
278+ ch, exists := c.responses[idKey]
279+ c.mu.RUnlock()
280+
281+ if exists {
282+ ch <- &baseMessage
283+ c.mu.Lock()
284+ delete(c.responses, idKey)
285+ c.mu.Unlock()
286+ }
287+ }
288+}
289+
290+func (c *SSE) SetNotificationHandler(handler func(notification mcp.JSONRPCNotification)) {
291+ c.notifyMu.Lock()
292+ defer c.notifyMu.Unlock()
293+ c.onNotification = handler
294+}
295+
296+// SendRequest sends a JSON-RPC request to the server and waits for a response.
297+// Returns the raw JSON response message or an error if the request fails.
298+func (c *SSE) SendRequest(
299+ ctx context.Context,
300+ request JSONRPCRequest,
301+) (*JSONRPCResponse, error) {
302+
303+ if !c.started.Load() {
304+ return nil, fmt.Errorf("transport not started yet")
305+ }
306+ if c.closed.Load() {
307+ return nil, fmt.Errorf("transport has been closed")
308+ }
309+ if c.endpoint == nil {
310+ return nil, fmt.Errorf("endpoint not received")
311+ }
312+
313+ // Marshal request
314+ requestBytes, err := json.Marshal(request)
315+ if err != nil {
316+ return nil, fmt.Errorf("failed to marshal request: %w", err)
317+ }
318+
319+ // Create HTTP request
320+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpoint.String(), bytes.NewReader(requestBytes))
321+ if err != nil {
322+ return nil, fmt.Errorf("failed to create request: %w", err)
323+ }
324+
325+ // Set headers
326+ req.Header.Set("Content-Type", "application/json")
327+ for k, v := range c.headers {
328+ req.Header.Set(k, v)
329+ }
330+
331+ // Add OAuth authorization if configured
332+ if c.oauthHandler != nil {
333+ authHeader, err := c.oauthHandler.GetAuthorizationHeader(ctx)
334+ if err != nil {
335+ // If we get an authorization error, return a specific error that can be handled by the client
336+ if err.Error() == "no valid token available, authorization required" {
337+ return nil, &OAuthAuthorizationRequiredError{
338+ Handler: c.oauthHandler,
339+ }
340+ }
341+ return nil, fmt.Errorf("failed to get authorization header: %w", err)
342+ }
343+ req.Header.Set("Authorization", authHeader)
344+ }
345+
346+ if c.headerFunc != nil {
347+ for k, v := range c.headerFunc(ctx) {
348+ req.Header.Set(k, v)
349+ }
350+ }
351+
352+ // Create string key for map lookup
353+ idKey := request.ID.String()
354+
355+ // Register response channel
356+ responseChan := make(chan *JSONRPCResponse, 1)
357+ c.mu.Lock()
358+ c.responses[idKey] = responseChan
359+ c.mu.Unlock()
360+ deleteResponseChan := func() {
361+ c.mu.Lock()
362+ delete(c.responses, idKey)
363+ c.mu.Unlock()
364+ }
365+
366+ // Send request
367+ resp, err := c.httpClient.Do(req)
368+ if err != nil {
369+ deleteResponseChan()
370+ return nil, fmt.Errorf("failed to send request: %w", err)
371+ }
372+
373+ // Drain any outstanding io
374+ body, err := io.ReadAll(resp.Body)
375+ resp.Body.Close()
376+
377+ if err != nil {
378+ return nil, fmt.Errorf("failed to read response body: %w", err)
379+ }
380+
381+ // Check if we got an error response
382+ if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
383+ deleteResponseChan()
384+
385+ // Handle OAuth unauthorized error
386+ if resp.StatusCode == http.StatusUnauthorized && c.oauthHandler != nil {
387+ return nil, &OAuthAuthorizationRequiredError{
388+ Handler: c.oauthHandler,
389+ }
390+ }
391+
392+ return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, body)
393+ }
394+
395+ select {
396+ case <-ctx.Done():
397+ deleteResponseChan()
398+ return nil, ctx.Err()
399+ case response, ok := <-responseChan:
400+ if ok {
401+ return response, nil
402+ }
403+ return nil, fmt.Errorf("connection has been closed")
404+ }
405+}
406+
407+// Close shuts down the SSE client connection and cleans up any pending responses.
408+// Returns an error if the shutdown process fails.
409+func (c *SSE) Close() error {
410+ if !c.closed.CompareAndSwap(false, true) {
411+ return nil // Already closed
412+ }
413+
414+ if c.cancelSSEStream != nil {
415+ // It could stop the sse stream body, to quit the readSSE loop immediately
416+ // Also, it could quit start() immediately if not receiving the endpoint
417+ c.cancelSSEStream()
418+ }
419+
420+ // Clean up any pending responses
421+ c.mu.Lock()
422+ for _, ch := range c.responses {
423+ close(ch)
424+ }
425+ c.responses = make(map[string]chan *JSONRPCResponse)
426+ c.mu.Unlock()
427+
428+ return nil
429+}
430+
431+// SendNotification sends a JSON-RPC notification to the server without expecting a response.
432+func (c *SSE) SendNotification(ctx context.Context, notification mcp.JSONRPCNotification) error {
433+ if c.endpoint == nil {
434+ return fmt.Errorf("endpoint not received")
435+ }
436+
437+ notificationBytes, err := json.Marshal(notification)
438+ if err != nil {
439+ return fmt.Errorf("failed to marshal notification: %w", err)
440+ }
441+
442+ req, err := http.NewRequestWithContext(
443+ ctx,
444+ "POST",
445+ c.endpoint.String(),
446+ bytes.NewReader(notificationBytes),
447+ )
448+ if err != nil {
449+ return fmt.Errorf("failed to create notification request: %w", err)
450+ }
451+
452+ req.Header.Set("Content-Type", "application/json")
453+ // Set custom HTTP headers
454+ for k, v := range c.headers {
455+ req.Header.Set(k, v)
456+ }
457+
458+ // Add OAuth authorization if configured
459+ if c.oauthHandler != nil {
460+ authHeader, err := c.oauthHandler.GetAuthorizationHeader(ctx)
461+ if err != nil {
462+ // If we get an authorization error, return a specific error that can be handled by the client
463+ if errors.Is(err, ErrOAuthAuthorizationRequired) {
464+ return &OAuthAuthorizationRequiredError{
465+ Handler: c.oauthHandler,
466+ }
467+ }
468+ return fmt.Errorf("failed to get authorization header: %w", err)
469+ }
470+ req.Header.Set("Authorization", authHeader)
471+ }
472+
473+ if c.headerFunc != nil {
474+ for k, v := range c.headerFunc(ctx) {
475+ req.Header.Set(k, v)
476+ }
477+ }
478+
479+ resp, err := c.httpClient.Do(req)
480+ if err != nil {
481+ return fmt.Errorf("failed to send notification: %w", err)
482+ }
483+ defer resp.Body.Close()
484+
485+ if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
486+ // Handle OAuth unauthorized error
487+ if resp.StatusCode == http.StatusUnauthorized && c.oauthHandler != nil {
488+ return &OAuthAuthorizationRequiredError{
489+ Handler: c.oauthHandler,
490+ }
491+ }
492+
493+ body, _ := io.ReadAll(resp.Body)
494+ return fmt.Errorf(
495+ "notification failed with status %d: %s",
496+ resp.StatusCode,
497+ body,
498+ )
499+ }
500+
501+ return nil
502+}
503+
504+// GetEndpoint returns the current endpoint URL for the SSE connection.
505+func (c *SSE) GetEndpoint() *url.URL {
506+ return c.endpoint
507+}
508+
509+// GetBaseURL returns the base URL set in the SSE constructor.
510+func (c *SSE) GetBaseURL() *url.URL {
511+ return c.baseURL
512+}
513+
514+// GetOAuthHandler returns the OAuth handler if configured
515+func (c *SSE) GetOAuthHandler() *OAuthHandler {
516+ return c.oauthHandler
517+}
518+
519+// IsOAuthEnabled returns true if OAuth is enabled
520+func (c *SSE) IsOAuthEnabled() bool {
521+ return c.oauthHandler != nil
522+}
vendor/github.com/mark3labs/mcp-go/client/transport/stdio.gonew file+288
@@ -0,0 +1,288 @@
1+package transport
2+
3+import (
4+ "bufio"
5+ "context"
6+ "encoding/json"
7+ "fmt"
8+ "io"
9+ "os"
10+ "os/exec"
11+ "sync"
12+
13+ "github.com/mark3labs/mcp-go/mcp"
14+)
15+
16+// Stdio implements the transport layer of the MCP protocol using stdio communication.
17+// It launches a subprocess and communicates with it via standard input/output streams
18+// using JSON-RPC messages. The client handles message routing between requests and
19+// responses, and supports asynchronous notifications.
20+type Stdio struct {
21+ command string
22+ args []string
23+ env []string
24+
25+ cmd *exec.Cmd
26+ stdin io.WriteCloser
27+ stdout *bufio.Reader
28+ stderr io.ReadCloser
29+ responses map[string]chan *JSONRPCResponse
30+ mu sync.RWMutex
31+ done chan struct{}
32+ onNotification func(mcp.JSONRPCNotification)
33+ notifyMu sync.RWMutex
34+}
35+
36+// NewIO returns a new stdio-based transport using existing input, output, and
37+// logging streams instead of spawning a subprocess.
38+// This is useful for testing and simulating client behavior.
39+func NewIO(input io.Reader, output io.WriteCloser, logging io.ReadCloser) *Stdio {
40+ return &Stdio{
41+ stdin: output,
42+ stdout: bufio.NewReader(input),
43+ stderr: logging,
44+
45+ responses: make(map[string]chan *JSONRPCResponse),
46+ done: make(chan struct{}),
47+ }
48+}
49+
50+// NewStdio creates a new stdio transport to communicate with a subprocess.
51+// It launches the specified command with given arguments and sets up stdin/stdout pipes for communication.
52+// Returns an error if the subprocess cannot be started or the pipes cannot be created.
53+func NewStdio(
54+ command string,
55+ env []string,
56+ args ...string,
57+) *Stdio {
58+
59+ client := &Stdio{
60+ command: command,
61+ args: args,
62+ env: env,
63+
64+ responses: make(map[string]chan *JSONRPCResponse),
65+ done: make(chan struct{}),
66+ }
67+
68+ return client
69+}
70+
71+func (c *Stdio) Start(ctx context.Context) error {
72+ if err := c.spawnCommand(ctx); err != nil {
73+ return err
74+ }
75+
76+ ready := make(chan struct{})
77+ go func() {
78+ close(ready)
79+ c.readResponses()
80+ }()
81+ <-ready
82+
83+ return nil
84+}
85+
86+// spawnCommand spawns a new process running c.command.
87+func (c *Stdio) spawnCommand(ctx context.Context) error {
88+ if c.command == "" {
89+ return nil
90+ }
91+
92+ cmd := exec.CommandContext(ctx, c.command, c.args...)
93+
94+ mergedEnv := os.Environ()
95+ mergedEnv = append(mergedEnv, c.env...)
96+
97+ cmd.Env = mergedEnv
98+
99+ stdin, err := cmd.StdinPipe()
100+ if err != nil {
101+ return fmt.Errorf("failed to create stdin pipe: %w", err)
102+ }
103+
104+ stdout, err := cmd.StdoutPipe()
105+ if err != nil {
106+ return fmt.Errorf("failed to create stdout pipe: %w", err)
107+ }
108+
109+ stderr, err := cmd.StderrPipe()
110+ if err != nil {
111+ return fmt.Errorf("failed to create stderr pipe: %w", err)
112+ }
113+
114+ c.cmd = cmd
115+ c.stdin = stdin
116+ c.stderr = stderr
117+ c.stdout = bufio.NewReader(stdout)
118+
119+ if err := cmd.Start(); err != nil {
120+ return fmt.Errorf("failed to start command: %w", err)
121+ }
122+
123+ return nil
124+}
125+
126+// Close shuts down the stdio client, closing the stdin pipe and waiting for the subprocess to exit.
127+// Returns an error if there are issues closing stdin or waiting for the subprocess to terminate.
128+func (c *Stdio) Close() error {
129+ select {
130+ case <-c.done:
131+ return nil
132+ default:
133+ }
134+ // cancel all in-flight request
135+ close(c.done)
136+
137+ if err := c.stdin.Close(); err != nil {
138+ return fmt.Errorf("failed to close stdin: %w", err)
139+ }
140+ if err := c.stderr.Close(); err != nil {
141+ return fmt.Errorf("failed to close stderr: %w", err)
142+ }
143+
144+ if c.cmd != nil {
145+ return c.cmd.Wait()
146+ }
147+
148+ return nil
149+}
150+
151+// SetNotificationHandler sets the handler function to be called when a notification is received.
152+// Only one handler can be set at a time; setting a new one replaces the previous handler.
153+func (c *Stdio) SetNotificationHandler(
154+ handler func(notification mcp.JSONRPCNotification),
155+) {
156+ c.notifyMu.Lock()
157+ defer c.notifyMu.Unlock()
158+ c.onNotification = handler
159+}
160+
161+// readResponses continuously reads and processes responses from the server's stdout.
162+// It handles both responses to requests and notifications, routing them appropriately.
163+// Runs until the done channel is closed or an error occurs reading from stdout.
164+func (c *Stdio) readResponses() {
165+ for {
166+ select {
167+ case <-c.done:
168+ return
169+ default:
170+ line, err := c.stdout.ReadString('\n')
171+ if err != nil {
172+ if err != io.EOF {
173+ fmt.Printf("Error reading response: %v\n", err)
174+ }
175+ return
176+ }
177+
178+ var baseMessage JSONRPCResponse
179+ if err := json.Unmarshal([]byte(line), &baseMessage); err != nil {
180+ continue
181+ }
182+
183+ // Handle notification
184+ if baseMessage.ID.IsNil() {
185+ var notification mcp.JSONRPCNotification
186+ if err := json.Unmarshal([]byte(line), &notification); err != nil {
187+ continue
188+ }
189+ c.notifyMu.RLock()
190+ if c.onNotification != nil {
191+ c.onNotification(notification)
192+ }
193+ c.notifyMu.RUnlock()
194+ continue
195+ }
196+
197+ // Create string key for map lookup
198+ idKey := baseMessage.ID.String()
199+
200+ c.mu.RLock()
201+ ch, exists := c.responses[idKey]
202+ c.mu.RUnlock()
203+
204+ if exists {
205+ ch <- &baseMessage
206+ c.mu.Lock()
207+ delete(c.responses, idKey)
208+ c.mu.Unlock()
209+ }
210+ }
211+ }
212+}
213+
214+// SendRequest sends a JSON-RPC request to the server and waits for a response.
215+// It creates a unique request ID, sends the request over stdin, and waits for
216+// the corresponding response or context cancellation.
217+// Returns the raw JSON response message or an error if the request fails.
218+func (c *Stdio) SendRequest(
219+ ctx context.Context,
220+ request JSONRPCRequest,
221+) (*JSONRPCResponse, error) {
222+ if c.stdin == nil {
223+ return nil, fmt.Errorf("stdio client not started")
224+ }
225+
226+ // Marshal request
227+ requestBytes, err := json.Marshal(request)
228+ if err != nil {
229+ return nil, fmt.Errorf("failed to marshal request: %w", err)
230+ }
231+ requestBytes = append(requestBytes, '\n')
232+
233+ // Create string key for map lookup
234+ idKey := request.ID.String()
235+
236+ // Register response channel
237+ responseChan := make(chan *JSONRPCResponse, 1)
238+ c.mu.Lock()
239+ c.responses[idKey] = responseChan
240+ c.mu.Unlock()
241+ deleteResponseChan := func() {
242+ c.mu.Lock()
243+ delete(c.responses, idKey)
244+ c.mu.Unlock()
245+ }
246+
247+ // Send request
248+ if _, err := c.stdin.Write(requestBytes); err != nil {
249+ deleteResponseChan()
250+ return nil, fmt.Errorf("failed to write request: %w", err)
251+ }
252+
253+ select {
254+ case <-ctx.Done():
255+ deleteResponseChan()
256+ return nil, ctx.Err()
257+ case response := <-responseChan:
258+ return response, nil
259+ }
260+}
261+
262+// SendNotification sends a json RPC Notification to the server.
263+func (c *Stdio) SendNotification(
264+ ctx context.Context,
265+ notification mcp.JSONRPCNotification,
266+) error {
267+ if c.stdin == nil {
268+ return fmt.Errorf("stdio client not started")
269+ }
270+
271+ notificationBytes, err := json.Marshal(notification)
272+ if err != nil {
273+ return fmt.Errorf("failed to marshal notification: %w", err)
274+ }
275+ notificationBytes = append(notificationBytes, '\n')
276+
277+ if _, err := c.stdin.Write(notificationBytes); err != nil {
278+ return fmt.Errorf("failed to write notification: %w", err)
279+ }
280+
281+ return nil
282+}
283+
284+// Stderr returns a reader for the stderr output of the subprocess.
285+// This can be used to capture error messages or logs from the subprocess.
286+func (c *Stdio) Stderr() io.Reader {
287+ return c.stderr
288+}
vendor/github.com/mark3labs/mcp-go/client/transport/streamable_http.gonew file+515
@@ -0,0 +1,515 @@
1+package transport
2+
3+import (
4+ "bufio"
5+ "bytes"
6+ "context"
7+ "encoding/json"
8+ "errors"
9+ "fmt"
10+ "io"
11+ "mime"
12+ "net/http"
13+ "net/url"
14+ "strings"
15+ "sync"
16+ "sync/atomic"
17+ "time"
18+
19+ "github.com/mark3labs/mcp-go/mcp"
20+)
21+
22+type StreamableHTTPCOption func(*StreamableHTTP)
23+
24+// WithHTTPClient sets a custom HTTP client on the StreamableHTTP transport.
25+func WithHTTPBasicClient(client *http.Client) StreamableHTTPCOption {
26+ return func(sc *StreamableHTTP) {
27+ sc.httpClient = client
28+ }
29+}
30+
31+func WithHTTPHeaders(headers map[string]string) StreamableHTTPCOption {
32+ return func(sc *StreamableHTTP) {
33+ sc.headers = headers
34+ }
35+}
36+
37+func WithHTTPHeaderFunc(headerFunc HTTPHeaderFunc) StreamableHTTPCOption {
38+ return func(sc *StreamableHTTP) {
39+ sc.headerFunc = headerFunc
40+ }
41+}
42+
43+// WithHTTPTimeout sets the timeout for a HTTP request and stream.
44+func WithHTTPTimeout(timeout time.Duration) StreamableHTTPCOption {
45+ return func(sc *StreamableHTTP) {
46+ sc.httpClient.Timeout = timeout
47+ }
48+}
49+
50+// WithHTTPOAuth enables OAuth authentication for the client.
51+func WithHTTPOAuth(config OAuthConfig) StreamableHTTPCOption {
52+ return func(sc *StreamableHTTP) {
53+ sc.oauthHandler = NewOAuthHandler(config)
54+ }
55+}
56+
57+// StreamableHTTP implements Streamable HTTP transport.
58+//
59+// It transmits JSON-RPC messages over individual HTTP requests. One message per request.
60+// The HTTP response body can either be a single JSON-RPC response,
61+// or an upgraded SSE stream that concludes with a JSON-RPC response for the same request.
62+//
63+// https://modelcontextprotocol.io/specification/2025-03-26/basic/transports
64+//
65+// The current implementation does not support the following features:
66+// - batching
67+// - continuously listening for server notifications when no request is in flight
68+// (https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#listening-for-messages-from-the-server)
69+// - resuming stream
70+// (https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#resumability-and-redelivery)
71+// - server -> client request
72+type StreamableHTTP struct {
73+ serverURL *url.URL
74+ httpClient *http.Client
75+ headers map[string]string
76+ headerFunc HTTPHeaderFunc
77+
78+ sessionID atomic.Value // string
79+
80+ notificationHandler func(mcp.JSONRPCNotification)
81+ notifyMu sync.RWMutex
82+
83+ closed chan struct{}
84+
85+ // OAuth support
86+ oauthHandler *OAuthHandler
87+}
88+
89+// NewStreamableHTTP creates a new Streamable HTTP transport with the given server URL.
90+// Returns an error if the URL is invalid.
91+func NewStreamableHTTP(serverURL string, options ...StreamableHTTPCOption) (*StreamableHTTP, error) {
92+ parsedURL, err := url.Parse(serverURL)
93+ if err != nil {
94+ return nil, fmt.Errorf("invalid URL: %w", err)
95+ }
96+
97+ smc := &StreamableHTTP{
98+ serverURL: parsedURL,
99+ httpClient: &http.Client{},
100+ headers: make(map[string]string),
101+ closed: make(chan struct{}),
102+ }
103+ smc.sessionID.Store("") // set initial value to simplify later usage
104+
105+ for _, opt := range options {
106+ opt(smc)
107+ }
108+
109+ // If OAuth is configured, set the base URL for metadata discovery
110+ if smc.oauthHandler != nil {
111+ // Extract base URL from server URL for metadata discovery
112+ baseURL := fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host)
113+ smc.oauthHandler.SetBaseURL(baseURL)
114+ }
115+
116+ return smc, nil
117+}
118+
119+// Start initiates the HTTP connection to the server.
120+func (c *StreamableHTTP) Start(ctx context.Context) error {
121+ // For Streamable HTTP, we don't need to establish a persistent connection
122+ return nil
123+}
124+
125+// Close closes the all the HTTP connections to the server.
126+func (c *StreamableHTTP) Close() error {
127+ select {
128+ case <-c.closed:
129+ return nil
130+ default:
131+ }
132+ // Cancel all in-flight requests
133+ close(c.closed)
134+
135+ sessionId := c.sessionID.Load().(string)
136+ if sessionId != "" {
137+ c.sessionID.Store("")
138+
139+ // notify server session closed
140+ go func() {
141+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
142+ defer cancel()
143+ req, err := http.NewRequestWithContext(ctx, http.MethodDelete, c.serverURL.String(), nil)
144+ if err != nil {
145+ fmt.Printf("failed to create close request\n: %v", err)
146+ return
147+ }
148+ req.Header.Set(headerKeySessionID, sessionId)
149+ res, err := c.httpClient.Do(req)
150+ if err != nil {
151+ fmt.Printf("failed to send close request\n: %v", err)
152+ return
153+ }
154+ res.Body.Close()
155+ }()
156+ }
157+
158+ return nil
159+}
160+
161+const (
162+ headerKeySessionID = "Mcp-Session-Id"
163+)
164+
165+// ErrOAuthAuthorizationRequired is a sentinel error for OAuth authorization required
166+var ErrOAuthAuthorizationRequired = errors.New("no valid token available, authorization required")
167+
168+// OAuthAuthorizationRequiredError is returned when OAuth authorization is required
169+type OAuthAuthorizationRequiredError struct {
170+ Handler *OAuthHandler
171+}
172+
173+func (e *OAuthAuthorizationRequiredError) Error() string {
174+ return ErrOAuthAuthorizationRequired.Error()
175+}
176+
177+func (e *OAuthAuthorizationRequiredError) Unwrap() error {
178+ return ErrOAuthAuthorizationRequired
179+}
180+
181+// SendRequest sends a JSON-RPC request to the server and waits for a response.
182+// Returns the raw JSON response message or an error if the request fails.
183+func (c *StreamableHTTP) SendRequest(
184+ ctx context.Context,
185+ request JSONRPCRequest,
186+) (*JSONRPCResponse, error) {
187+
188+ // Create a combined context that could be canceled when the client is closed
189+ newCtx, cancel := context.WithCancel(ctx)
190+ defer cancel()
191+ go func() {
192+ select {
193+ case <-c.closed:
194+ cancel()
195+ case <-newCtx.Done():
196+ // The original context was canceled, no need to do anything
197+ }
198+ }()
199+ ctx = newCtx
200+
201+ // Marshal request
202+ requestBody, err := json.Marshal(request)
203+ if err != nil {
204+ return nil, fmt.Errorf("failed to marshal request: %w", err)
205+ }
206+
207+ // Create HTTP request
208+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.serverURL.String(), bytes.NewReader(requestBody))
209+ if err != nil {
210+ return nil, fmt.Errorf("failed to create request: %w", err)
211+ }
212+
213+ // Set headers
214+ req.Header.Set("Content-Type", "application/json")
215+ req.Header.Set("Accept", "application/json, text/event-stream")
216+ sessionID := c.sessionID.Load()
217+ if sessionID != "" {
218+ req.Header.Set(headerKeySessionID, sessionID.(string))
219+ }
220+ for k, v := range c.headers {
221+ req.Header.Set(k, v)
222+ }
223+
224+ // Add OAuth authorization if configured
225+ if c.oauthHandler != nil {
226+ authHeader, err := c.oauthHandler.GetAuthorizationHeader(ctx)
227+ if err != nil {
228+ // If we get an authorization error, return a specific error that can be handled by the client
229+ if err.Error() == "no valid token available, authorization required" {
230+ return nil, &OAuthAuthorizationRequiredError{
231+ Handler: c.oauthHandler,
232+ }
233+ }
234+ return nil, fmt.Errorf("failed to get authorization header: %w", err)
235+ }
236+ req.Header.Set("Authorization", authHeader)
237+ }
238+
239+ if c.headerFunc != nil {
240+ for k, v := range c.headerFunc(ctx) {
241+ req.Header.Set(k, v)
242+ }
243+ }
244+
245+ // Send request
246+ resp, err := c.httpClient.Do(req)
247+ if err != nil {
248+ return nil, fmt.Errorf("failed to send request: %w", err)
249+ }
250+ defer resp.Body.Close()
251+
252+ // Check if we got an error response
253+ if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
254+ // handle session closed
255+ if resp.StatusCode == http.StatusNotFound {
256+ c.sessionID.CompareAndSwap(sessionID, "")
257+ return nil, fmt.Errorf("session terminated (404). need to re-initialize")
258+ }
259+
260+ // Handle OAuth unauthorized error
261+ if resp.StatusCode == http.StatusUnauthorized && c.oauthHandler != nil {
262+ return nil, &OAuthAuthorizationRequiredError{
263+ Handler: c.oauthHandler,
264+ }
265+ }
266+
267+ // handle error response
268+ var errResponse JSONRPCResponse
269+ body, _ := io.ReadAll(resp.Body)
270+ if err := json.Unmarshal(body, &errResponse); err == nil {
271+ return &errResponse, nil
272+ }
273+ return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, body)
274+ }
275+
276+ if request.Method == string(mcp.MethodInitialize) {
277+ // saved the received session ID in the response
278+ // empty session ID is allowed
279+ if sessionID := resp.Header.Get(headerKeySessionID); sessionID != "" {
280+ c.sessionID.Store(sessionID)
281+ }
282+ }
283+
284+ // Handle different response types
285+ mediaType, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
286+ switch mediaType {
287+ case "application/json":
288+ // Single response
289+ var response JSONRPCResponse
290+ if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
291+ return nil, fmt.Errorf("failed to decode response: %w", err)
292+ }
293+
294+ // should not be a notification
295+ if response.ID.IsNil() {
296+ return nil, fmt.Errorf("response should contain RPC id: %v", response)
297+ }
298+
299+ return &response, nil
300+
301+ case "text/event-stream":
302+ // Server is using SSE for streaming responses
303+ return c.handleSSEResponse(ctx, resp.Body)
304+
305+ default:
306+ return nil, fmt.Errorf("unexpected content type: %s", resp.Header.Get("Content-Type"))
307+ }
308+}
309+
310+// handleSSEResponse processes an SSE stream for a specific request.
311+// It returns the final result for the request once received, or an error.
312+func (c *StreamableHTTP) handleSSEResponse(ctx context.Context, reader io.ReadCloser) (*JSONRPCResponse, error) {
313+
314+ // Create a channel for this specific request
315+ responseChan := make(chan *JSONRPCResponse, 1)
316+
317+ ctx, cancel := context.WithCancel(ctx)
318+ defer cancel()
319+
320+ // Start a goroutine to process the SSE stream
321+ go func() {
322+ // only close responseChan after readingSSE()
323+ defer close(responseChan)
324+
325+ c.readSSE(ctx, reader, func(event, data string) {
326+
327+ // (unsupported: batching)
328+
329+ var message JSONRPCResponse
330+ if err := json.Unmarshal([]byte(data), &message); err != nil {
331+ fmt.Printf("failed to unmarshal message: %v\n", err)
332+ return
333+ }
334+
335+ // Handle notification
336+ if message.ID.IsNil() {
337+ var notification mcp.JSONRPCNotification
338+ if err := json.Unmarshal([]byte(data), &notification); err != nil {
339+ fmt.Printf("failed to unmarshal notification: %v\n", err)
340+ return
341+ }
342+ c.notifyMu.RLock()
343+ if c.notificationHandler != nil {
344+ c.notificationHandler(notification)
345+ }
346+ c.notifyMu.RUnlock()
347+ return
348+ }
349+
350+ responseChan <- &message
351+ })
352+ }()
353+
354+ // Wait for the response or context cancellation
355+ select {
356+ case response := <-responseChan:
357+ if response == nil {
358+ return nil, fmt.Errorf("unexpected nil response")
359+ }
360+ return response, nil
361+ case <-ctx.Done():
362+ return nil, ctx.Err()
363+ }
364+}
365+
366+// readSSE reads the SSE stream(reader) and calls the handler for each event and data pair.
367+// It will end when the reader is closed (or the context is done).
368+func (c *StreamableHTTP) readSSE(ctx context.Context, reader io.ReadCloser, handler func(event, data string)) {
369+ defer reader.Close()
370+
371+ br := bufio.NewReader(reader)
372+ var event, data string
373+
374+ for {
375+ select {
376+ case <-ctx.Done():
377+ return
378+ default:
379+ line, err := br.ReadString('\n')
380+ if err != nil {
381+ if err == io.EOF {
382+ // Process any pending event before exit
383+ if data != "" {
384+ // If no event type is specified, use empty string (default event type)
385+ if event == "" {
386+ event = "message"
387+ }
388+ handler(event, data)
389+ }
390+ return
391+ }
392+ select {
393+ case <-ctx.Done():
394+ return
395+ default:
396+ fmt.Printf("SSE stream error: %v\n", err)
397+ return
398+ }
399+ }
400+
401+ // Remove only newline markers
402+ line = strings.TrimRight(line, "\r\n")
403+ if line == "" {
404+ // Empty line means end of event
405+ if data != "" {
406+ // If no event type is specified, use empty string (default event type)
407+ if event == "" {
408+ event = "message"
409+ }
410+ handler(event, data)
411+ event = ""
412+ data = ""
413+ }
414+ continue
415+ }
416+
417+ if strings.HasPrefix(line, "event:") {
418+ event = strings.TrimSpace(strings.TrimPrefix(line, "event:"))
419+ } else if strings.HasPrefix(line, "data:") {
420+ data = strings.TrimSpace(strings.TrimPrefix(line, "data:"))
421+ }
422+ }
423+ }
424+}
425+
426+func (c *StreamableHTTP) SendNotification(ctx context.Context, notification mcp.JSONRPCNotification) error {
427+
428+ // Marshal request
429+ requestBody, err := json.Marshal(notification)
430+ if err != nil {
431+ return fmt.Errorf("failed to marshal notification: %w", err)
432+ }
433+
434+ // Create HTTP request
435+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.serverURL.String(), bytes.NewReader(requestBody))
436+ if err != nil {
437+ return fmt.Errorf("failed to create request: %w", err)
438+ }
439+
440+ // Set headers
441+ req.Header.Set("Content-Type", "application/json")
442+ req.Header.Set("Accept", "application/json, text/event-stream")
443+ if sessionID := c.sessionID.Load(); sessionID != "" {
444+ req.Header.Set(headerKeySessionID, sessionID.(string))
445+ }
446+ for k, v := range c.headers {
447+ req.Header.Set(k, v)
448+ }
449+
450+ // Add OAuth authorization if configured
451+ if c.oauthHandler != nil {
452+ authHeader, err := c.oauthHandler.GetAuthorizationHeader(ctx)
453+ if err != nil {
454+ // If we get an authorization error, return a specific error that can be handled by the client
455+ if errors.Is(err, ErrOAuthAuthorizationRequired) {
456+ return &OAuthAuthorizationRequiredError{
457+ Handler: c.oauthHandler,
458+ }
459+ }
460+ return fmt.Errorf("failed to get authorization header: %w", err)
461+ }
462+ req.Header.Set("Authorization", authHeader)
463+ }
464+
465+ if c.headerFunc != nil {
466+ for k, v := range c.headerFunc(ctx) {
467+ req.Header.Set(k, v)
468+ }
469+ }
470+
471+ // Send request
472+ resp, err := c.httpClient.Do(req)
473+ if err != nil {
474+ return fmt.Errorf("failed to send request: %w", err)
475+ }
476+ defer resp.Body.Close()
477+
478+ if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
479+ // Handle OAuth unauthorized error
480+ if resp.StatusCode == http.StatusUnauthorized && c.oauthHandler != nil {
481+ return &OAuthAuthorizationRequiredError{
482+ Handler: c.oauthHandler,
483+ }
484+ }
485+
486+ body, _ := io.ReadAll(resp.Body)
487+ return fmt.Errorf(
488+ "notification failed with status %d: %s",
489+ resp.StatusCode,
490+ body,
491+ )
492+ }
493+
494+ return nil
495+}
496+
497+func (c *StreamableHTTP) SetNotificationHandler(handler func(mcp.JSONRPCNotification)) {
498+ c.notifyMu.Lock()
499+ defer c.notifyMu.Unlock()
500+ c.notificationHandler = handler
501+}
502+
503+func (c *StreamableHTTP) GetSessionId() string {
504+ return c.sessionID.Load().(string)
505+}
506+
507+// GetOAuthHandler returns the OAuth handler if configured
508+func (c *StreamableHTTP) GetOAuthHandler() *OAuthHandler {
509+ return c.oauthHandler
510+}
511+
512+// IsOAuthEnabled returns true if OAuth is enabled
513+func (c *StreamableHTTP) IsOAuthEnabled() bool {
514+ return c.oauthHandler != nil
515+}
vendor/github.com/mark3labs/mcp-go/client/types.godeleted−8
@@ -1,8 +0,0 @@
1−package client
2−
3−import "encoding/json"
4−
5−type RPCResponse struct {
6− Error *string
7− Response *json.RawMessage
8−}
vendor/github.com/mark3labs/mcp-go/mcp/prompts.go+14−7
@@ -19,12 +19,14 @@ type ListPromptsResult struct {
19// server.
19// server.
20type GetPromptRequest struct {
20type GetPromptRequest struct {
21 Request
21 Request
22− Params struct {
22+ Params GetPromptParams `json:"params"`
23+}
24+
25+type GetPromptParams struct {
23− // The name of the prompt or prompt template.
26+ // The name of the prompt or prompt template.
24− Name string `json:"name"`
27+ Name string `json:"name"`
25− // Arguments to use for templating the prompt.
28+ // Arguments to use for templating the prompt.
26− Arguments map[string]string `json:"arguments,omitempty"`
29+ Arguments map[string]string `json:"arguments,omitempty"`
27− } `json:"params"`
28}
30}
29
31
30// GetPromptResult is the server's response to a prompts/get request from the
32// GetPromptResult is the server's response to a prompts/get request from the
@@ -50,6 +52,11 @@ type Prompt struct {
50 Arguments []PromptArgument `json:"arguments,omitempty"`
52 Arguments []PromptArgument `json:"arguments,omitempty"`
51}
53}
52
54
55+// GetName returns the name of the prompt.
56+func (p Prompt) GetName() string {
57+ return p.Name
58+}
59+
53// PromptArgument describes an argument that a prompt template can accept.
60// PromptArgument describes an argument that a prompt template can accept.
54// When a prompt includes arguments, clients must provide values for all
61// When a prompt includes arguments, clients must provide values for all
55// required arguments when making a prompts/get request.
62// required arguments when making a prompts/get request.
@@ -78,7 +85,7 @@ const (
78// resources from the MCP server.
85// resources from the MCP server.
79type PromptMessage struct {
86type PromptMessage struct {
80 Role Role `json:"role"`
87 Role Role `json:"role"`
81− Content Content `json:"content"` // Can be TextContent, ImageContent, or EmbeddedResource
88+ Content Content `json:"content"` // Can be TextContent, ImageContent, AudioContent or EmbeddedResource
82}
89}
83
90
84// PromptListChangedNotification is an optional notification from the server
91// PromptListChangedNotification is an optional notification from the server
vendor/github.com/mark3labs/mcp-go/mcp/resources.go+2−8
@@ -43,10 +43,7 @@ func WithMIMEType(mimeType string) ResourceOption {
43func WithAnnotations(audience []Role, priority float64) ResourceOption {
43func WithAnnotations(audience []Role, priority float64) ResourceOption {
44 return func(r *Resource) {
44 return func(r *Resource) {
45 if r.Annotations == nil {
45 if r.Annotations == nil {
46− r.Annotations = &struct {
46+ r.Annotations = &Annotations{}
47− Audience []Role `json:"audience,omitempty"`
48− Priority float64 `json:"priority,omitempty"`
49− }{}
50 }
47 }
51 r.Annotations.Audience = audience
48 r.Annotations.Audience = audience
52 r.Annotations.Priority = priority
49 r.Annotations.Priority = priority
@@ -94,10 +91,7 @@ func WithTemplateMIMEType(mimeType string) ResourceTemplateOption {
94func WithTemplateAnnotations(audience []Role, priority float64) ResourceTemplateOption {
91func WithTemplateAnnotations(audience []Role, priority float64) ResourceTemplateOption {
95 return func(t *ResourceTemplate) {
92 return func(t *ResourceTemplate) {
96 if t.Annotations == nil {
93 if t.Annotations == nil {
97− t.Annotations = &struct {
94+ t.Annotations = &Annotations{}
98− Audience []Role `json:"audience,omitempty"`
99− Priority float64 `json:"priority,omitempty"`
100− }{}
101 }
95 }
102 t.Annotations.Audience = audience
96 t.Annotations.Audience = audience
103 t.Annotations.Priority = priority
97 t.Annotations.Priority = priority
vendor/github.com/mark3labs/mcp-go/mcp/tools.go+565−77
@@ -4,6 +4,8 @@ import (
4 "encoding/json"
4 "encoding/json"
5 "errors"
5 "errors"
6 "fmt"
6 "fmt"
7+ "reflect"
8+ "strconv"
7)
9)
8
10
9var errToolSchemaConflict = errors.New("provide either InputSchema or RawInputSchema, not both")
11var errToolSchemaConflict = errors.New("provide either InputSchema or RawInputSchema, not both")
@@ -33,7 +35,7 @@ type ListToolsResult struct {
33// should be reported as an MCP error response.
35// should be reported as an MCP error response.
34type CallToolResult struct {
36type CallToolResult struct {
35 Result
37 Result
36− Content []Content `json:"content"` // Can be TextContent, ImageContent, or EmbeddedResource
38+ Content []Content `json:"content"` // Can be TextContent, ImageContent, AudioContent, or EmbeddedResource
37 // Whether the tool call ended in an error.
39 // Whether the tool call ended in an error.
38 //
40 //
39 // If not set, this is assumed to be false (the call was successful).
41 // If not set, this is assumed to be false (the call was successful).
@@ -43,19 +45,420 @@ type CallToolResult struct {
43// CallToolRequest is used by the client to invoke a tool provided by the server.
45// CallToolRequest is used by the client to invoke a tool provided by the server.
44type CallToolRequest struct {
46type CallToolRequest struct {
45 Request
47 Request
46− Params struct {
48+ Params CallToolParams `json:"params"`
49+}
50+
51+type CallToolParams struct {
47− Name string `json:"name"`
52+ Name string `json:"name"`
48− Arguments map[string]interface{} `json:"arguments,omitempty"`
53+ Arguments any `json:"arguments,omitempty"`
49− Meta *struct {
54+ Meta *Meta `json:"_meta,omitempty"`
50− // If specified, the caller is requesting out-of-band progress
55+}
51− // notifications for this request (as represented by
56+
52− // notifications/progress). The value of this parameter is an
57+// GetArguments returns the Arguments as map[string]any for backward compatibility
53− // opaque token that will be attached to any subsequent
58+// If Arguments is not a map, it returns an empty map
54− // notifications. The receiver is not obligated to provide these
59+func (r CallToolRequest) GetArguments() map[string]any {
55− // notifications.
60+ if args, ok := r.Params.Arguments.(map[string]any); ok {
56− ProgressToken ProgressToken `json:"progressToken,omitempty"`
61+ return args
57− } `json:"_meta,omitempty"`
62+ }
58− } `json:"params"`
63+ return nil
64+}
65+
66+// GetRawArguments returns the Arguments as-is without type conversion
67+// This allows users to access the raw arguments in any format
68+func (r CallToolRequest) GetRawArguments() any {
69+ return r.Params.Arguments
70+}
71+
72+// BindArguments unmarshals the Arguments into the provided struct
73+// This is useful for working with strongly-typed arguments
74+func (r CallToolRequest) BindArguments(target any) error {
75+ if target == nil || reflect.ValueOf(target).Kind() != reflect.Ptr {
76+ return fmt.Errorf("target must be a non-nil pointer")
77+ }
78+
79+ // Fast-path: already raw JSON
80+ if raw, ok := r.Params.Arguments.(json.RawMessage); ok {
81+ return json.Unmarshal(raw, target)
82+ }
83+
84+ data, err := json.Marshal(r.Params.Arguments)
85+ if err != nil {
86+ return fmt.Errorf("failed to marshal arguments: %w", err)
87+ }
88+
89+ return json.Unmarshal(data, target)
90+}
91+
92+// GetString returns a string argument by key, or the default value if not found
93+func (r CallToolRequest) GetString(key string, defaultValue string) string {
94+ args := r.GetArguments()
95+ if val, ok := args[key]; ok {
96+ if str, ok := val.(string); ok {
97+ return str
98+ }
99+ }
100+ return defaultValue
101+}
102+
103+// RequireString returns a string argument by key, or an error if not found or not a string
104+func (r CallToolRequest) RequireString(key string) (string, error) {
105+ args := r.GetArguments()
106+ if val, ok := args[key]; ok {
107+ if str, ok := val.(string); ok {
108+ return str, nil
109+ }
110+ return "", fmt.Errorf("argument %q is not a string", key)
111+ }
112+ return "", fmt.Errorf("required argument %q not found", key)
113+}
114+
115+// GetInt returns an int argument by key, or the default value if not found
116+func (r CallToolRequest) GetInt(key string, defaultValue int) int {
117+ args := r.GetArguments()
118+ if val, ok := args[key]; ok {
119+ switch v := val.(type) {
120+ case int:
121+ return v
122+ case float64:
123+ return int(v)
124+ case string:
125+ if i, err := strconv.Atoi(v); err == nil {
126+ return i
127+ }
128+ }
129+ }
130+ return defaultValue
131+}
132+
133+// RequireInt returns an int argument by key, or an error if not found or not convertible to int
134+func (r CallToolRequest) RequireInt(key string) (int, error) {
135+ args := r.GetArguments()
136+ if val, ok := args[key]; ok {
137+ switch v := val.(type) {
138+ case int:
139+ return v, nil
140+ case float64:
141+ return int(v), nil
142+ case string:
143+ if i, err := strconv.Atoi(v); err == nil {
144+ return i, nil
145+ }
146+ return 0, fmt.Errorf("argument %q cannot be converted to int", key)
147+ default:
148+ return 0, fmt.Errorf("argument %q is not an int", key)
149+ }
150+ }
151+ return 0, fmt.Errorf("required argument %q not found", key)
152+}
153+
154+// GetFloat returns a float64 argument by key, or the default value if not found
155+func (r CallToolRequest) GetFloat(key string, defaultValue float64) float64 {
156+ args := r.GetArguments()
157+ if val, ok := args[key]; ok {
158+ switch v := val.(type) {
159+ case float64:
160+ return v
161+ case int:
162+ return float64(v)
163+ case string:
164+ if f, err := strconv.ParseFloat(v, 64); err == nil {
165+ return f
166+ }
167+ }
168+ }
169+ return defaultValue
170+}
171+
172+// RequireFloat returns a float64 argument by key, or an error if not found or not convertible to float64
173+func (r CallToolRequest) RequireFloat(key string) (float64, error) {
174+ args := r.GetArguments()
175+ if val, ok := args[key]; ok {
176+ switch v := val.(type) {
177+ case float64:
178+ return v, nil
179+ case int:
180+ return float64(v), nil
181+ case string:
182+ if f, err := strconv.ParseFloat(v, 64); err == nil {
183+ return f, nil
184+ }
185+ return 0, fmt.Errorf("argument %q cannot be converted to float64", key)
186+ default:
187+ return 0, fmt.Errorf("argument %q is not a float64", key)
188+ }
189+ }
190+ return 0, fmt.Errorf("required argument %q not found", key)
191+}
192+
193+// GetBool returns a bool argument by key, or the default value if not found
194+func (r CallToolRequest) GetBool(key string, defaultValue bool) bool {
195+ args := r.GetArguments()
196+ if val, ok := args[key]; ok {
197+ switch v := val.(type) {
198+ case bool:
199+ return v
200+ case string:
201+ if b, err := strconv.ParseBool(v); err == nil {
202+ return b
203+ }
204+ case int:
205+ return v != 0
206+ case float64:
207+ return v != 0
208+ }
209+ }
210+ return defaultValue
211+}
212+
213+// RequireBool returns a bool argument by key, or an error if not found or not convertible to bool
214+func (r CallToolRequest) RequireBool(key string) (bool, error) {
215+ args := r.GetArguments()
216+ if val, ok := args[key]; ok {
217+ switch v := val.(type) {
218+ case bool:
219+ return v, nil
220+ case string:
221+ if b, err := strconv.ParseBool(v); err == nil {
222+ return b, nil
223+ }
224+ return false, fmt.Errorf("argument %q cannot be converted to bool", key)
225+ case int:
226+ return v != 0, nil
227+ case float64:
228+ return v != 0, nil
229+ default:
230+ return false, fmt.Errorf("argument %q is not a bool", key)
231+ }
232+ }
233+ return false, fmt.Errorf("required argument %q not found", key)
234+}
235+
236+// GetStringSlice returns a string slice argument by key, or the default value if not found
237+func (r CallToolRequest) GetStringSlice(key string, defaultValue []string) []string {
238+ args := r.GetArguments()
239+ if val, ok := args[key]; ok {
240+ switch v := val.(type) {
241+ case []string:
242+ return v
243+ case []any:
244+ result := make([]string, 0, len(v))
245+ for _, item := range v {
246+ if str, ok := item.(string); ok {
247+ result = append(result, str)
248+ }
249+ }
250+ return result
251+ }
252+ }
253+ return defaultValue
254+}
255+
256+// RequireStringSlice returns a string slice argument by key, or an error if not found or not convertible to string slice
257+func (r CallToolRequest) RequireStringSlice(key string) ([]string, error) {
258+ args := r.GetArguments()
259+ if val, ok := args[key]; ok {
260+ switch v := val.(type) {
261+ case []string:
262+ return v, nil
263+ case []any:
264+ result := make([]string, 0, len(v))
265+ for i, item := range v {
266+ if str, ok := item.(string); ok {
267+ result = append(result, str)
268+ } else {
269+ return nil, fmt.Errorf("item %d in argument %q is not a string", i, key)
270+ }
271+ }
272+ return result, nil
273+ default:
274+ return nil, fmt.Errorf("argument %q is not a string slice", key)
275+ }
276+ }
277+ return nil, fmt.Errorf("required argument %q not found", key)
278+}
279+
280+// GetIntSlice returns an int slice argument by key, or the default value if not found
281+func (r CallToolRequest) GetIntSlice(key string, defaultValue []int) []int {
282+ args := r.GetArguments()
283+ if val, ok := args[key]; ok {
284+ switch v := val.(type) {
285+ case []int:
286+ return v
287+ case []any:
288+ result := make([]int, 0, len(v))
289+ for _, item := range v {
290+ switch num := item.(type) {
291+ case int:
292+ result = append(result, num)
293+ case float64:
294+ result = append(result, int(num))
295+ case string:
296+ if i, err := strconv.Atoi(num); err == nil {
297+ result = append(result, i)
298+ }
299+ }
300+ }
301+ return result
302+ }
303+ }
304+ return defaultValue
305+}
306+
307+// RequireIntSlice returns an int slice argument by key, or an error if not found or not convertible to int slice
308+func (r CallToolRequest) RequireIntSlice(key string) ([]int, error) {
309+ args := r.GetArguments()
310+ if val, ok := args[key]; ok {
311+ switch v := val.(type) {
312+ case []int:
313+ return v, nil
314+ case []any:
315+ result := make([]int, 0, len(v))
316+ for i, item := range v {
317+ switch num := item.(type) {
318+ case int:
319+ result = append(result, num)
320+ case float64:
321+ result = append(result, int(num))
322+ case string:
323+ if i, err := strconv.Atoi(num); err == nil {
324+ result = append(result, i)
325+ } else {
326+ return nil, fmt.Errorf("item %d in argument %q cannot be converted to int", i, key)
327+ }
328+ default:
329+ return nil, fmt.Errorf("item %d in argument %q is not an int", i, key)
330+ }
331+ }
332+ return result, nil
333+ default:
334+ return nil, fmt.Errorf("argument %q is not an int slice", key)
335+ }
336+ }
337+ return nil, fmt.Errorf("required argument %q not found", key)
338+}
339+
340+// GetFloatSlice returns a float64 slice argument by key, or the default value if not found
341+func (r CallToolRequest) GetFloatSlice(key string, defaultValue []float64) []float64 {
342+ args := r.GetArguments()
343+ if val, ok := args[key]; ok {
344+ switch v := val.(type) {
345+ case []float64:
346+ return v
347+ case []any:
348+ result := make([]float64, 0, len(v))
349+ for _, item := range v {
350+ switch num := item.(type) {
351+ case float64:
352+ result = append(result, num)
353+ case int:
354+ result = append(result, float64(num))
355+ case string:
356+ if f, err := strconv.ParseFloat(num, 64); err == nil {
357+ result = append(result, f)
358+ }
359+ }
360+ }
361+ return result
362+ }
363+ }
364+ return defaultValue
365+}
366+
367+// RequireFloatSlice returns a float64 slice argument by key, or an error if not found or not convertible to float64 slice
368+func (r CallToolRequest) RequireFloatSlice(key string) ([]float64, error) {
369+ args := r.GetArguments()
370+ if val, ok := args[key]; ok {
371+ switch v := val.(type) {
372+ case []float64:
373+ return v, nil
374+ case []any:
375+ result := make([]float64, 0, len(v))
376+ for i, item := range v {
377+ switch num := item.(type) {
378+ case float64:
379+ result = append(result, num)
380+ case int:
381+ result = append(result, float64(num))
382+ case string:
383+ if f, err := strconv.ParseFloat(num, 64); err == nil {
384+ result = append(result, f)
385+ } else {
386+ return nil, fmt.Errorf("item %d in argument %q cannot be converted to float64", i, key)
387+ }
388+ default:
389+ return nil, fmt.Errorf("item %d in argument %q is not a float64", i, key)
390+ }
391+ }
392+ return result, nil
393+ default:
394+ return nil, fmt.Errorf("argument %q is not a float64 slice", key)
395+ }
396+ }
397+ return nil, fmt.Errorf("required argument %q not found", key)
398+}
399+
400+// GetBoolSlice returns a bool slice argument by key, or the default value if not found
401+func (r CallToolRequest) GetBoolSlice(key string, defaultValue []bool) []bool {
402+ args := r.GetArguments()
403+ if val, ok := args[key]; ok {
404+ switch v := val.(type) {
405+ case []bool:
406+ return v
407+ case []any:
408+ result := make([]bool, 0, len(v))
409+ for _, item := range v {
410+ switch b := item.(type) {
411+ case bool:
412+ result = append(result, b)
413+ case string:
414+ if parsed, err := strconv.ParseBool(b); err == nil {
415+ result = append(result, parsed)
416+ }
417+ case int:
418+ result = append(result, b != 0)
419+ case float64:
420+ result = append(result, b != 0)
421+ }
422+ }
423+ return result
424+ }
425+ }
426+ return defaultValue
427+}
428+
429+// RequireBoolSlice returns a bool slice argument by key, or an error if not found or not convertible to bool slice
430+func (r CallToolRequest) RequireBoolSlice(key string) ([]bool, error) {
431+ args := r.GetArguments()
432+ if val, ok := args[key]; ok {
433+ switch v := val.(type) {
434+ case []bool:
435+ return v, nil
436+ case []any:
437+ result := make([]bool, 0, len(v))
438+ for i, item := range v {
439+ switch b := item.(type) {
440+ case bool:
441+ result = append(result, b)
442+ case string:
443+ if parsed, err := strconv.ParseBool(b); err == nil {
444+ result = append(result, parsed)
445+ } else {
446+ return nil, fmt.Errorf("item %d in argument %q cannot be converted to bool", i, key)
447+ }
448+ case int:
449+ result = append(result, b != 0)
450+ case float64:
451+ result = append(result, b != 0)
452+ default:
453+ return nil, fmt.Errorf("item %d in argument %q is not a bool", i, key)
454+ }
455+ }
456+ return result, nil
457+ default:
458+ return nil, fmt.Errorf("argument %q is not a bool slice", key)
459+ }
460+ }
461+ return nil, fmt.Errorf("required argument %q not found", key)
59}
462}
60
463
61// ToolListChangedNotification is an optional notification from the server to
464// ToolListChangedNotification is an optional notification from the server to
@@ -75,13 +478,20 @@ type Tool struct {
75 InputSchema ToolInputSchema `json:"inputSchema"`
478 InputSchema ToolInputSchema `json:"inputSchema"`
76 // Alternative to InputSchema - allows arbitrary JSON Schema to be provided
479 // Alternative to InputSchema - allows arbitrary JSON Schema to be provided
77 RawInputSchema json.RawMessage `json:"-"` // Hide this from JSON marshaling
480 RawInputSchema json.RawMessage `json:"-"` // Hide this from JSON marshaling
481+ // Optional properties describing tool behavior
482+ Annotations ToolAnnotation `json:"annotations"`
483+}
484+
485+// GetName returns the name of the tool.
486+func (t Tool) GetName() string {
487+ return t.Name
78}
488}
79
489
80// MarshalJSON implements the json.Marshaler interface for Tool.
490// MarshalJSON implements the json.Marshaler interface for Tool.
81// It handles marshaling either InputSchema or RawInputSchema based on which is set.
491// It handles marshaling either InputSchema or RawInputSchema based on which is set.
82func (t Tool) MarshalJSON() ([]byte, error) {
492func (t Tool) MarshalJSON() ([]byte, error) {
83 // Create a map to build the JSON structure
493 // Create a map to build the JSON structure
84− m := make(map[string]interface{}, 3)
494+ m := make(map[string]any, 3)
85
495
86 // Add the name and description
496 // Add the name and description
87 m["name"] = t.Name
497 m["name"] = t.Name
@@ -100,13 +510,45 @@ func (t Tool) MarshalJSON() ([]byte, error) {
100 m["inputSchema"] = t.InputSchema
510 m["inputSchema"] = t.InputSchema
101 }
511 }
102
512
513+ m["annotations"] = t.Annotations
514+
103 return json.Marshal(m)
515 return json.Marshal(m)
104}
516}
105
517
106type ToolInputSchema struct {
518type ToolInputSchema struct {
107− Type string `json:"type"`
519+ Type string `json:"type"`
108− Properties map[string]interface{} `json:"properties"`
520+ Properties map[string]any `json:"properties,omitempty"`
109− Required []string `json:"required,omitempty"`
521+ Required []string `json:"required,omitempty"`
522+}
523+
524+// MarshalJSON implements the json.Marshaler interface for ToolInputSchema.
525+func (tis ToolInputSchema) MarshalJSON() ([]byte, error) {
526+ m := make(map[string]any)
527+ m["type"] = tis.Type
528+
529+ // Marshal Properties to '{}' rather than `nil` when its length equals zero
530+ if tis.Properties != nil {
531+ m["properties"] = tis.Properties
532+ }
533+
534+ if len(tis.Required) > 0 {
535+ m["required"] = tis.Required
536+ }
537+
538+ return json.Marshal(m)
539+}
540+
541+type ToolAnnotation struct {
542+ // Human-readable title for the tool
543+ Title string `json:"title,omitempty"`
544+ // If true, the tool does not modify its environment
545+ ReadOnlyHint *bool `json:"readOnlyHint,omitempty"`
546+ // If true, the tool may perform destructive updates
547+ DestructiveHint *bool `json:"destructiveHint,omitempty"`
548+ // If true, repeated calls with same args have no additional effect
549+ IdempotentHint *bool `json:"idempotentHint,omitempty"`
550+ // If true, tool interacts with external entities
551+ OpenWorldHint *bool `json:"openWorldHint,omitempty"`
110}
552}
111
553
112// ToolOption is a function that configures a Tool.
554// ToolOption is a function that configures a Tool.
@@ -115,7 +557,7 @@ type ToolOption func(*Tool)
115
557
116// PropertyOption is a function that configures a property in a Tool's input schema.
558// PropertyOption is a function that configures a property in a Tool's input schema.
117// It allows for flexible configuration of JSON Schema properties using the functional options pattern.
559// It allows for flexible configuration of JSON Schema properties using the functional options pattern.
118−type PropertyOption func(map[string]interface{})
560+type PropertyOption func(map[string]any)
119
561
120//
562//
121// Core Tool Functions
563// Core Tool Functions
@@ -129,9 +571,16 @@ func NewTool(name string, opts ...ToolOption) Tool {
129 Name: name,
571 Name: name,
130 InputSchema: ToolInputSchema{
572 InputSchema: ToolInputSchema{
131 Type: "object",
573 Type: "object",
132− Properties: make(map[string]interface{}),
574+ Properties: make(map[string]any),
133 Required: nil, // Will be omitted from JSON if empty
575 Required: nil, // Will be omitted from JSON if empty
134 },
576 },
577+ Annotations: ToolAnnotation{
578+ Title: "",
579+ ReadOnlyHint: ToBoolPtr(false),
580+ DestructiveHint: ToBoolPtr(true),
581+ IdempotentHint: ToBoolPtr(false),
582+ OpenWorldHint: ToBoolPtr(true),
583+ },
135 }
584 }
136
585
137 for _, opt := range opts {
586 for _, opt := range opts {
@@ -166,6 +615,53 @@ func WithDescription(description string) ToolOption {
166 }
615 }
167}
616}
168
617
618+// WithToolAnnotation adds optional hints about the Tool.
619+func WithToolAnnotation(annotation ToolAnnotation) ToolOption {
620+ return func(t *Tool) {
621+ t.Annotations = annotation
622+ }
623+}
624+
625+// WithTitleAnnotation sets the Title field of the Tool's Annotations.
626+// It provides a human-readable title for the tool.
627+func WithTitleAnnotation(title string) ToolOption {
628+ return func(t *Tool) {
629+ t.Annotations.Title = title
630+ }
631+}
632+
633+// WithReadOnlyHintAnnotation sets the ReadOnlyHint field of the Tool's Annotations.
634+// If true, it indicates the tool does not modify its environment.
635+func WithReadOnlyHintAnnotation(value bool) ToolOption {
636+ return func(t *Tool) {
637+ t.Annotations.ReadOnlyHint = &value
638+ }
639+}
640+
641+// WithDestructiveHintAnnotation sets the DestructiveHint field of the Tool's Annotations.
642+// If true, it indicates the tool may perform destructive updates.
643+func WithDestructiveHintAnnotation(value bool) ToolOption {
644+ return func(t *Tool) {
645+ t.Annotations.DestructiveHint = &value
646+ }
647+}
648+
649+// WithIdempotentHintAnnotation sets the IdempotentHint field of the Tool's Annotations.
650+// If true, it indicates repeated calls with the same arguments have no additional effect.
651+func WithIdempotentHintAnnotation(value bool) ToolOption {
652+ return func(t *Tool) {
653+ t.Annotations.IdempotentHint = &value
654+ }
655+}
656+
657+// WithOpenWorldHintAnnotation sets the OpenWorldHint field of the Tool's Annotations.
658+// If true, it indicates the tool interacts with external entities.
659+func WithOpenWorldHintAnnotation(value bool) ToolOption {
660+ return func(t *Tool) {
661+ t.Annotations.OpenWorldHint = &value
662+ }
663+}
664+
169//
665//
170// Common Property Options
666// Common Property Options
171//
667//
@@ -173,7 +669,7 @@ func WithDescription(description string) ToolOption {
173// Description adds a description to a property in the JSON Schema.
669// Description adds a description to a property in the JSON Schema.
174// The description should explain the purpose and expected values of the property.
670// The description should explain the purpose and expected values of the property.
175func Description(desc string) PropertyOption {
671func Description(desc string) PropertyOption {
176− return func(schema map[string]interface{}) {
672+ return func(schema map[string]any) {
177 schema["description"] = desc
673 schema["description"] = desc
178 }
674 }
179}
675}
@@ -181,7 +677,7 @@ func Description(desc string) PropertyOption {
181// Required marks a property as required in the tool's input schema.
677// Required marks a property as required in the tool's input schema.
182// Required properties must be provided when using the tool.
678// Required properties must be provided when using the tool.
183func Required() PropertyOption {
679func Required() PropertyOption {
184− return func(schema map[string]interface{}) {
680+ return func(schema map[string]any) {
185 schema["required"] = true
681 schema["required"] = true
186 }
682 }
187}
683}
@@ -189,7 +685,7 @@ func Required() PropertyOption {
189// Title adds a display-friendly title to a property in the JSON Schema.
685// Title adds a display-friendly title to a property in the JSON Schema.
190// This title can be used by UI components to show a more readable property name.
686// This title can be used by UI components to show a more readable property name.
191func Title(title string) PropertyOption {
687func Title(title string) PropertyOption {
192− return func(schema map[string]interface{}) {
688+ return func(schema map[string]any) {
193 schema["title"] = title
689 schema["title"] = title
194 }
690 }
195}
691}
@@ -201,7 +697,7 @@ func Title(title string) PropertyOption {
201// DefaultString sets the default value for a string property.
697// DefaultString sets the default value for a string property.
202// This value will be used if the property is not explicitly provided.
698// This value will be used if the property is not explicitly provided.
203func DefaultString(value string) PropertyOption {
699func DefaultString(value string) PropertyOption {
204− return func(schema map[string]interface{}) {
700+ return func(schema map[string]any) {
205 schema["default"] = value
701 schema["default"] = value
206 }
702 }
207}
703}
@@ -209,7 +705,7 @@ func DefaultString(value string) PropertyOption {
209// Enum specifies a list of allowed values for a string property.
705// Enum specifies a list of allowed values for a string property.
210// The property value must be one of the specified enum values.
706// The property value must be one of the specified enum values.
211func Enum(values ...string) PropertyOption {
707func Enum(values ...string) PropertyOption {
212− return func(schema map[string]interface{}) {
708+ return func(schema map[string]any) {
213 schema["enum"] = values
709 schema["enum"] = values
214 }
710 }
215}
711}
@@ -217,7 +713,7 @@ func Enum(values ...string) PropertyOption {
217// MaxLength sets the maximum length for a string property.
713// MaxLength sets the maximum length for a string property.
218// The string value must not exceed this length.
714// The string value must not exceed this length.
219func MaxLength(max int) PropertyOption {
715func MaxLength(max int) PropertyOption {
220− return func(schema map[string]interface{}) {
716+ return func(schema map[string]any) {
221 schema["maxLength"] = max
717 schema["maxLength"] = max
222 }
718 }
223}
719}
@@ -225,7 +721,7 @@ func MaxLength(max int) PropertyOption {
225// MinLength sets the minimum length for a string property.
721// MinLength sets the minimum length for a string property.
226// The string value must be at least this length.
722// The string value must be at least this length.
227func MinLength(min int) PropertyOption {
723func MinLength(min int) PropertyOption {
228− return func(schema map[string]interface{}) {
724+ return func(schema map[string]any) {
229 schema["minLength"] = min
725 schema["minLength"] = min
230 }
726 }
231}
727}
@@ -233,7 +729,7 @@ func MinLength(min int) PropertyOption {
233// Pattern sets a regex pattern that a string property must match.
729// Pattern sets a regex pattern that a string property must match.
234// The string value must conform to the specified regular expression.
730// The string value must conform to the specified regular expression.
235func Pattern(pattern string) PropertyOption {
731func Pattern(pattern string) PropertyOption {
236− return func(schema map[string]interface{}) {
732+ return func(schema map[string]any) {
237 schema["pattern"] = pattern
733 schema["pattern"] = pattern
238 }
734 }
239}
735}
@@ -245,7 +741,7 @@ func Pattern(pattern string) PropertyOption {
245// DefaultNumber sets the default value for a number property.
741// DefaultNumber sets the default value for a number property.
246// This value will be used if the property is not explicitly provided.
742// This value will be used if the property is not explicitly provided.
247func DefaultNumber(value float64) PropertyOption {
743func DefaultNumber(value float64) PropertyOption {
248− return func(schema map[string]interface{}) {
744+ return func(schema map[string]any) {
249 schema["default"] = value
745 schema["default"] = value
250 }
746 }
251}
747}
@@ -253,7 +749,7 @@ func DefaultNumber(value float64) PropertyOption {
253// Max sets the maximum value for a number property.
749// Max sets the maximum value for a number property.
254// The number value must not exceed this maximum.
750// The number value must not exceed this maximum.
255func Max(max float64) PropertyOption {
751func Max(max float64) PropertyOption {
256− return func(schema map[string]interface{}) {
752+ return func(schema map[string]any) {
257 schema["maximum"] = max
753 schema["maximum"] = max
258 }
754 }
259}
755}
@@ -261,7 +757,7 @@ func Max(max float64) PropertyOption {
261// Min sets the minimum value for a number property.
757// Min sets the minimum value for a number property.
262// The number value must not be less than this minimum.
758// The number value must not be less than this minimum.
263func Min(min float64) PropertyOption {
759func Min(min float64) PropertyOption {
264− return func(schema map[string]interface{}) {
760+ return func(schema map[string]any) {
265 schema["minimum"] = min
761 schema["minimum"] = min
266 }
762 }
267}
763}
@@ -269,7 +765,7 @@ func Min(min float64) PropertyOption {
269// MultipleOf specifies that a number must be a multiple of the given value.
765// MultipleOf specifies that a number must be a multiple of the given value.
270// The number value must be divisible by this value.
766// The number value must be divisible by this value.
271func MultipleOf(value float64) PropertyOption {
767func MultipleOf(value float64) PropertyOption {
272− return func(schema map[string]interface{}) {
768+ return func(schema map[string]any) {
273 schema["multipleOf"] = value
769 schema["multipleOf"] = value
274 }
770 }
275}
771}
@@ -281,7 +777,19 @@ func MultipleOf(value float64) PropertyOption {
281// DefaultBool sets the default value for a boolean property.
777// DefaultBool sets the default value for a boolean property.
282// This value will be used if the property is not explicitly provided.
778// This value will be used if the property is not explicitly provided.
283func DefaultBool(value bool) PropertyOption {
779func DefaultBool(value bool) PropertyOption {
284− return func(schema map[string]interface{}) {
780+ return func(schema map[string]any) {
781+ schema["default"] = value
782+ }
783+}
784+
785+//
786+// Array Property Options
787+//
788+
789+// DefaultArray sets the default value for an array property.
790+// This value will be used if the property is not explicitly provided.
791+func DefaultArray[T any](value []T) PropertyOption {
792+ return func(schema map[string]any) {
285 schema["default"] = value
793 schema["default"] = value
286 }
794 }
287}
795}
@@ -294,7 +802,7 @@ func DefaultBool(value bool) PropertyOption {
294// It accepts property options to configure the boolean property's behavior and constraints.
802// It accepts property options to configure the boolean property's behavior and constraints.
295func WithBoolean(name string, opts ...PropertyOption) ToolOption {
803func WithBoolean(name string, opts ...PropertyOption) ToolOption {
296 return func(t *Tool) {
804 return func(t *Tool) {
297− schema := map[string]interface{}{
805+ schema := map[string]any{
298 "type": "boolean",
806 "type": "boolean",
299 }
807 }
300
808
@@ -305,11 +813,7 @@ func WithBoolean(name string, opts ...PropertyOption) ToolOption {
305 // Remove required from property schema and add to InputSchema.required
813 // Remove required from property schema and add to InputSchema.required
306 if required, ok := schema["required"].(bool); ok && required {
814 if required, ok := schema["required"].(bool); ok && required {
307 delete(schema, "required")
815 delete(schema, "required")
308− if t.InputSchema.Required == nil {
309− t.InputSchema.Required = []string{name}
310− } else {
311− t.InputSchema.Required = append(t.InputSchema.Required, name)
816+ t.InputSchema.Required = append(t.InputSchema.Required, name)
312− }
313 }
817 }
314
818
315 t.InputSchema.Properties[name] = schema
819 t.InputSchema.Properties[name] = schema
@@ -320,7 +824,7 @@ func WithBoolean(name string, opts ...PropertyOption) ToolOption {
320// It accepts property options to configure the number property's behavior and constraints.
824// It accepts property options to configure the number property's behavior and constraints.
321func WithNumber(name string, opts ...PropertyOption) ToolOption {
825func WithNumber(name string, opts ...PropertyOption) ToolOption {
322 return func(t *Tool) {
826 return func(t *Tool) {
323− schema := map[string]interface{}{
827+ schema := map[string]any{
324 "type": "number",
828 "type": "number",
325 }
829 }
326
830
@@ -331,11 +835,7 @@ func WithNumber(name string, opts ...PropertyOption) ToolOption {
331 // Remove required from property schema and add to InputSchema.required
835 // Remove required from property schema and add to InputSchema.required
332 if required, ok := schema["required"].(bool); ok && required {
836 if required, ok := schema["required"].(bool); ok && required {
333 delete(schema, "required")
837 delete(schema, "required")
334− if t.InputSchema.Required == nil {
335− t.InputSchema.Required = []string{name}
336− } else {
337− t.InputSchema.Required = append(t.InputSchema.Required, name)
838+ t.InputSchema.Required = append(t.InputSchema.Required, name)
338− }
339 }
839 }
340
840
341 t.InputSchema.Properties[name] = schema
841 t.InputSchema.Properties[name] = schema
@@ -346,7 +846,7 @@ func WithNumber(name string, opts ...PropertyOption) ToolOption {
346// It accepts property options to configure the string property's behavior and constraints.
846// It accepts property options to configure the string property's behavior and constraints.
347func WithString(name string, opts ...PropertyOption) ToolOption {
847func WithString(name string, opts ...PropertyOption) ToolOption {
348 return func(t *Tool) {
848 return func(t *Tool) {
349− schema := map[string]interface{}{
849+ schema := map[string]any{
350 "type": "string",
850 "type": "string",
351 }
851 }
352
852
@@ -357,11 +857,7 @@ func WithString(name string, opts ...PropertyOption) ToolOption {
357 // Remove required from property schema and add to InputSchema.required
857 // Remove required from property schema and add to InputSchema.required
358 if required, ok := schema["required"].(bool); ok && required {
858 if required, ok := schema["required"].(bool); ok && required {
359 delete(schema, "required")
859 delete(schema, "required")
360− if t.InputSchema.Required == nil {
361− t.InputSchema.Required = []string{name}
362− } else {
363− t.InputSchema.Required = append(t.InputSchema.Required, name)
860+ t.InputSchema.Required = append(t.InputSchema.Required, name)
364− }
365 }
861 }
366
862
367 t.InputSchema.Properties[name] = schema
863 t.InputSchema.Properties[name] = schema
@@ -372,9 +868,9 @@ func WithString(name string, opts ...PropertyOption) ToolOption {
372// It accepts property options to configure the object property's behavior and constraints.
868// It accepts property options to configure the object property's behavior and constraints.
373func WithObject(name string, opts ...PropertyOption) ToolOption {
869func WithObject(name string, opts ...PropertyOption) ToolOption {
374 return func(t *Tool) {
870 return func(t *Tool) {
375− schema := map[string]interface{}{
871+ schema := map[string]any{
376 "type": "object",
872 "type": "object",
377− "properties": map[string]interface{}{},
873+ "properties": map[string]any{},
378 }
874 }
379
875
380 for _, opt := range opts {
876 for _, opt := range opts {
@@ -384,11 +880,7 @@ func WithObject(name string, opts ...PropertyOption) ToolOption {
384 // Remove required from property schema and add to InputSchema.required
880 // Remove required from property schema and add to InputSchema.required
385 if required, ok := schema["required"].(bool); ok && required {
881 if required, ok := schema["required"].(bool); ok && required {
386 delete(schema, "required")
882 delete(schema, "required")
387− if t.InputSchema.Required == nil {
388− t.InputSchema.Required = []string{name}
389− } else {
390− t.InputSchema.Required = append(t.InputSchema.Required, name)
883+ t.InputSchema.Required = append(t.InputSchema.Required, name)
391− }
392 }
884 }
393
885
394 t.InputSchema.Properties[name] = schema
886 t.InputSchema.Properties[name] = schema
@@ -399,7 +891,7 @@ func WithObject(name string, opts ...PropertyOption) ToolOption {
399// It accepts property options to configure the array property's behavior and constraints.
891// It accepts property options to configure the array property's behavior and constraints.
400func WithArray(name string, opts ...PropertyOption) ToolOption {
892func WithArray(name string, opts ...PropertyOption) ToolOption {
401 return func(t *Tool) {
893 return func(t *Tool) {
402− schema := map[string]interface{}{
894+ schema := map[string]any{
403 "type": "array",
895 "type": "array",
404 }
896 }
405
897
@@ -410,11 +902,7 @@ func WithArray(name string, opts ...PropertyOption) ToolOption {
410 // Remove required from property schema and add to InputSchema.required
902 // Remove required from property schema and add to InputSchema.required
411 if required, ok := schema["required"].(bool); ok && required {
903 if required, ok := schema["required"].(bool); ok && required {
412 delete(schema, "required")
904 delete(schema, "required")
413− if t.InputSchema.Required == nil {
414− t.InputSchema.Required = []string{name}
415− } else {
416− t.InputSchema.Required = append(t.InputSchema.Required, name)
905+ t.InputSchema.Required = append(t.InputSchema.Required, name)
417− }
418 }
906 }
419
907
420 t.InputSchema.Properties[name] = schema
908 t.InputSchema.Properties[name] = schema
@@ -422,65 +910,65 @@ func WithArray(name string, opts ...PropertyOption) ToolOption {
422}
910}
423
911
424// Properties defines the properties for an object schema
912// Properties defines the properties for an object schema
425−func Properties(props map[string]interface{}) PropertyOption {
913+func Properties(props map[string]any) PropertyOption {
426− return func(schema map[string]interface{}) {
914+ return func(schema map[string]any) {
427 schema["properties"] = props
915 schema["properties"] = props
428 }
916 }
429}
917}
430
918
431// AdditionalProperties specifies whether additional properties are allowed in the object
919// AdditionalProperties specifies whether additional properties are allowed in the object
432// or defines a schema for additional properties
920// or defines a schema for additional properties
433−func AdditionalProperties(schema interface{}) PropertyOption {
921+func AdditionalProperties(schema any) PropertyOption {
434− return func(schemaMap map[string]interface{}) {
922+ return func(schemaMap map[string]any) {
435 schemaMap["additionalProperties"] = schema
923 schemaMap["additionalProperties"] = schema
436 }
924 }
437}
925}
438
926
439// MinProperties sets the minimum number of properties for an object
927// MinProperties sets the minimum number of properties for an object
440func MinProperties(min int) PropertyOption {
928func MinProperties(min int) PropertyOption {
441− return func(schema map[string]interface{}) {
929+ return func(schema map[string]any) {
442 schema["minProperties"] = min
930 schema["minProperties"] = min
443 }
931 }
444}
932}
445
933
446// MaxProperties sets the maximum number of properties for an object
934// MaxProperties sets the maximum number of properties for an object
447func MaxProperties(max int) PropertyOption {
935func MaxProperties(max int) PropertyOption {
448− return func(schema map[string]interface{}) {
936+ return func(schema map[string]any) {
449 schema["maxProperties"] = max
937 schema["maxProperties"] = max
450 }
938 }
451}
939}
452
940
453// PropertyNames defines a schema for property names in an object
941// PropertyNames defines a schema for property names in an object
454−func PropertyNames(schema map[string]interface{}) PropertyOption {
942+func PropertyNames(schema map[string]any) PropertyOption {
455− return func(schemaMap map[string]interface{}) {
943+ return func(schemaMap map[string]any) {
456 schemaMap["propertyNames"] = schema
944 schemaMap["propertyNames"] = schema
457 }
945 }
458}
946}
459
947
460// Items defines the schema for array items
948// Items defines the schema for array items
461−func Items(schema interface{}) PropertyOption {
949+func Items(schema any) PropertyOption {
462− return func(schemaMap map[string]interface{}) {
950+ return func(schemaMap map[string]any) {
463 schemaMap["items"] = schema
951 schemaMap["items"] = schema
464 }
952 }
465}
953}
466
954
467// MinItems sets the minimum number of items for an array
955// MinItems sets the minimum number of items for an array
468func MinItems(min int) PropertyOption {
956func MinItems(min int) PropertyOption {
469− return func(schema map[string]interface{}) {
957+ return func(schema map[string]any) {
470 schema["minItems"] = min
958 schema["minItems"] = min
471 }
959 }
472}
960}
473
961
474// MaxItems sets the maximum number of items for an array
962// MaxItems sets the maximum number of items for an array
475func MaxItems(max int) PropertyOption {
963func MaxItems(max int) PropertyOption {
476− return func(schema map[string]interface{}) {
964+ return func(schema map[string]any) {
477 schema["maxItems"] = max
965 schema["maxItems"] = max
478 }
966 }
479}
967}
480
968
481// UniqueItems specifies whether array items must be unique
969// UniqueItems specifies whether array items must be unique
482func UniqueItems(unique bool) PropertyOption {
970func UniqueItems(unique bool) PropertyOption {
483− return func(schema map[string]interface{}) {
971+ return func(schema map[string]any) {
484 schema["uniqueItems"] = unique
972 schema["uniqueItems"] = unique
485 }
973 }
486}
974}
vendor/github.com/mark3labs/mcp-go/mcp/typed_tools.gonew file+20
@@ -0,0 +1,20 @@
1+package mcp
2+
3+import (
4+ "context"
5+ "fmt"
6+)
7+
8+// TypedToolHandlerFunc is a function that handles a tool call with typed arguments
9+type TypedToolHandlerFunc[T any] func(ctx context.Context, request CallToolRequest, args T) (*CallToolResult, error)
10+
11+// NewTypedToolHandler creates a ToolHandlerFunc that automatically binds arguments to a typed struct
12+func NewTypedToolHandler[T any](handler TypedToolHandlerFunc[T]) func(ctx context.Context, request CallToolRequest) (*CallToolResult, error) {
13+ return func(ctx context.Context, request CallToolRequest) (*CallToolResult, error) {
14+ var args T
15+ if err := request.BindArguments(&args); err != nil {
16+ return NewToolResultError(fmt.Sprintf("failed to bind arguments: %v", err)), nil
17+ }
18+ return handler(ctx, request, args)
19+ }
20+}
vendor/github.com/mark3labs/mcp-go/mcp/types.go+351−167
@@ -1,9 +1,12 @@
1−// Package mcp defines the core types and interfaces for the Model Control Protocol (MCP).
1+// Package mcp defines the core types and interfaces for the Model Context Protocol (MCP).
2// MCP is a protocol for communication between LLM-powered applications and their supporting services.
2// MCP is a protocol for communication between LLM-powered applications and their supporting services.
3package mcp
3package mcp
4
4
5import (
5import (
6 "encoding/json"
6 "encoding/json"
7+ "fmt"
8+ "maps"
9+ "strconv"
7
10
8 "github.com/yosida95/uritemplate/v3"
11 "github.com/yosida95/uritemplate/v3"
9)
12)
@@ -11,41 +14,59 @@ import (
11type MCPMethod string
14type MCPMethod string
12
15
13const (
16const (
14− // Initiates connection and negotiates protocol capabilities.
17+ // MethodInitialize initiates connection and negotiates protocol capabilities.
15− // https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/#initialization
18+ // https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/#initialization
16 MethodInitialize MCPMethod = "initialize"
19 MethodInitialize MCPMethod = "initialize"
17
20
18− // Verifies connection liveness between client and server.
21+ // MethodPing verifies connection liveness between client and server.
19− // https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/utilities/ping/
22+ // https://modelcontextprotocol.io/specification/2024-11-05/basic/utilities/ping/
20 MethodPing MCPMethod = "ping"
23 MethodPing MCPMethod = "ping"
21
24
22− // Lists all available server resources.
25+ // MethodResourcesList lists all available server resources.
23− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/resources/
26+ // https://modelcontextprotocol.io/specification/2024-11-05/server/resources/
24 MethodResourcesList MCPMethod = "resources/list"
27 MethodResourcesList MCPMethod = "resources/list"
25
28
26− // Provides URI templates for constructing resource URIs.
29+ // MethodResourcesTemplatesList provides URI templates for constructing resource URIs.
27− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/resources/
30+ // https://modelcontextprotocol.io/specification/2024-11-05/server/resources/
28 MethodResourcesTemplatesList MCPMethod = "resources/templates/list"
31 MethodResourcesTemplatesList MCPMethod = "resources/templates/list"
29
32
30− // Retrieves content of a specific resource by URI.
33+ // MethodResourcesRead retrieves content of a specific resource by URI.
31− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/resources/
34+ // https://modelcontextprotocol.io/specification/2024-11-05/server/resources/
32 MethodResourcesRead MCPMethod = "resources/read"
35 MethodResourcesRead MCPMethod = "resources/read"
33
36
34− // Lists all available prompt templates.
37+ // MethodPromptsList lists all available prompt templates.
35− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/prompts/
38+ // https://modelcontextprotocol.io/specification/2024-11-05/server/prompts/
36 MethodPromptsList MCPMethod = "prompts/list"
39 MethodPromptsList MCPMethod = "prompts/list"
37
40
38− // Retrieves a specific prompt template with filled parameters.
41+ // MethodPromptsGet retrieves a specific prompt template with filled parameters.
39− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/prompts/
42+ // https://modelcontextprotocol.io/specification/2024-11-05/server/prompts/
40 MethodPromptsGet MCPMethod = "prompts/get"
43 MethodPromptsGet MCPMethod = "prompts/get"
41
44
42− // Lists all available executable tools.
45+ // MethodToolsList lists all available executable tools.
43− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/
46+ // https://modelcontextprotocol.io/specification/2024-11-05/server/tools/
44 MethodToolsList MCPMethod = "tools/list"
47 MethodToolsList MCPMethod = "tools/list"
45
48
46− // Invokes a specific tool with provided parameters.
49+ // MethodToolsCall invokes a specific tool with provided parameters.
47− // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/
50+ // https://modelcontextprotocol.io/specification/2024-11-05/server/tools/
48 MethodToolsCall MCPMethod = "tools/call"
51 MethodToolsCall MCPMethod = "tools/call"
52+
53+ // MethodSetLogLevel configures the minimum log level for client
54+ // https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/logging
55+ MethodSetLogLevel MCPMethod = "logging/setLevel"
56+
57+ // MethodNotificationResourcesListChanged notifies when the list of available resources changes.
58+ // https://modelcontextprotocol.io/specification/2025-03-26/server/resources#list-changed-notification
59+ MethodNotificationResourcesListChanged = "notifications/resources/list_changed"
60+
61+ MethodNotificationResourceUpdated = "notifications/resources/updated"
62+
63+ // MethodNotificationPromptsListChanged notifies when the list of available prompt templates changes.
64+ // https://modelcontextprotocol.io/specification/2025-03-26/server/prompts#list-changed-notification
65+ MethodNotificationPromptsListChanged = "notifications/prompts/list_changed"
66+
67+ // MethodNotificationToolsListChanged notifies when the list of available tools changes.
68+ // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/list_changed/
69+ MethodNotificationToolsListChanged = "notifications/tools/list_changed"
49)
70)
50
71
51type URITemplate struct {
72type URITemplate struct {
@@ -53,7 +74,7 @@ type URITemplate struct {
53}
74}
54
75
55func (t *URITemplate) MarshalJSON() ([]byte, error) {
76func (t *URITemplate) MarshalJSON() ([]byte, error) {
56− return json.Marshal(t.Template.Raw())
77+ return json.Marshal(t.Raw())
57}
78}
58
79
59func (t *URITemplate) UnmarshalJSON(data []byte) error {
80func (t *URITemplate) UnmarshalJSON(data []byte) error {
@@ -72,36 +93,73 @@ func (t *URITemplate) UnmarshalJSON(data []byte) error {
72/* JSON-RPC types */
93/* JSON-RPC types */
73
94
74// JSONRPCMessage represents either a JSONRPCRequest, JSONRPCNotification, JSONRPCResponse, or JSONRPCError
95// JSONRPCMessage represents either a JSONRPCRequest, JSONRPCNotification, JSONRPCResponse, or JSONRPCError
75−type JSONRPCMessage interface{}
96+type JSONRPCMessage any
76
97
77// LATEST_PROTOCOL_VERSION is the most recent version of the MCP protocol.
98// LATEST_PROTOCOL_VERSION is the most recent version of the MCP protocol.
78−const LATEST_PROTOCOL_VERSION = "2024-11-05"
99+const LATEST_PROTOCOL_VERSION = "2025-03-26"
100+
101+// ValidProtocolVersions lists all known valid MCP protocol versions.
102+var ValidProtocolVersions = []string{
103+ "2024-11-05",
104+ LATEST_PROTOCOL_VERSION,
105+}
79
106
80// JSONRPC_VERSION is the version of JSON-RPC used by MCP.
107// JSONRPC_VERSION is the version of JSON-RPC used by MCP.
81const JSONRPC_VERSION = "2.0"
108const JSONRPC_VERSION = "2.0"
82
109
83// ProgressToken is used to associate progress notifications with the original request.
110// ProgressToken is used to associate progress notifications with the original request.
84−type ProgressToken interface{}
111+type ProgressToken any
85
112
86// Cursor is an opaque token used to represent a cursor for pagination.
113// Cursor is an opaque token used to represent a cursor for pagination.
87type Cursor string
114type Cursor string
88
115
116+// Meta is metadata attached to a request's parameters. This can include fields
117+// formally defined by the protocol or other arbitrary data.
118+type Meta struct {
119+ // If specified, the caller is requesting out-of-band progress
120+ // notifications for this request (as represented by
121+ // notifications/progress). The value of this parameter is an
122+ // opaque token that will be attached to any subsequent
123+ // notifications. The receiver is not obligated to provide these
124+ // notifications.
125+ ProgressToken ProgressToken
126+
127+ // AdditionalFields are any fields present in the Meta that are not
128+ // otherwise defined in the protocol.
129+ AdditionalFields map[string]any
130+}
131+
132+func (m *Meta) MarshalJSON() ([]byte, error) {
133+ raw := make(map[string]any)
134+ if m.ProgressToken != nil {
135+ raw["progressToken"] = m.ProgressToken
136+ }
137+ maps.Copy(raw, m.AdditionalFields)
138+
139+ return json.Marshal(raw)
140+}
141+
142+func (m *Meta) UnmarshalJSON(data []byte) error {
143+ raw := make(map[string]any)
144+ if err := json.Unmarshal(data, &raw); err != nil {
145+ return err
146+ }
147+ m.ProgressToken = raw["progressToken"]
148+ delete(raw, "progressToken")
149+ m.AdditionalFields = raw
150+ return nil
151+}
152+
89type Request struct {
153type Request struct {
90− Method string `json:"method"`
154+ Method string `json:"method"`
91− Params struct {
155+ Params RequestParams `json:"params,omitempty"`
92− Meta *struct {
156+}
93− // If specified, the caller is requesting out-of-band progress
157+
94− // notifications for this request (as represented by
158+type RequestParams struct {
95− // notifications/progress). The value of this parameter is an
96− // opaque token that will be attached to any subsequent
97− // notifications. The receiver is not obligated to provide these
98− // notifications.
99− ProgressToken ProgressToken `json:"progressToken,omitempty"`
100− } `json:"_meta,omitempty"`
159+ Meta *Meta `json:"_meta,omitempty"`
101− } `json:"params,omitempty"`
102−}
160+}
103−
161+
104−type Params map[string]interface{}
162+type Params map[string]any
105
163
106type Notification struct {
164type Notification struct {
107 Method string `json:"method"`
165 Method string `json:"method"`
@@ -111,16 +169,16 @@ type Notification struct {
111type NotificationParams struct {
169type NotificationParams struct {
112 // This parameter name is reserved by MCP to allow clients and
170 // This parameter name is reserved by MCP to allow clients and
113 // servers to attach additional metadata to their notifications.
171 // servers to attach additional metadata to their notifications.
114− Meta map[string]interface{} `json:"_meta,omitempty"`
172+ Meta map[string]any `json:"_meta,omitempty"`
115
173
116 // Additional fields can be added to this map
174 // Additional fields can be added to this map
117− AdditionalFields map[string]interface{} `json:"-"`
175+ AdditionalFields map[string]any `json:"-"`
118}
176}
119
177
120// MarshalJSON implements custom JSON marshaling
178// MarshalJSON implements custom JSON marshaling
121func (p NotificationParams) MarshalJSON() ([]byte, error) {
179func (p NotificationParams) MarshalJSON() ([]byte, error) {
122 // Create a map to hold all fields
180 // Create a map to hold all fields
123− m := make(map[string]interface{})
181+ m := make(map[string]any)
124
182
125 // Add Meta if it exists
183 // Add Meta if it exists
126 if p.Meta != nil {
184 if p.Meta != nil {
@@ -141,24 +199,24 @@ func (p NotificationParams) MarshalJSON() ([]byte, error) {
141// UnmarshalJSON implements custom JSON unmarshaling
199// UnmarshalJSON implements custom JSON unmarshaling
142func (p *NotificationParams) UnmarshalJSON(data []byte) error {
200func (p *NotificationParams) UnmarshalJSON(data []byte) error {
143 // Create a map to hold all fields
201 // Create a map to hold all fields
144− var m map[string]interface{}
202+ var m map[string]any
145 if err := json.Unmarshal(data, &m); err != nil {
203 if err := json.Unmarshal(data, &m); err != nil {
146 return err
204 return err
147 }
205 }
148
206
149 // Initialize maps if they're nil
207 // Initialize maps if they're nil
150 if p.Meta == nil {
208 if p.Meta == nil {
151− p.Meta = make(map[string]interface{})
209+ p.Meta = make(map[string]any)
152 }
210 }
153 if p.AdditionalFields == nil {
211 if p.AdditionalFields == nil {
154− p.AdditionalFields = make(map[string]interface{})
212+ p.AdditionalFields = make(map[string]any)
155 }
213 }
156
214
157 // Process all fields
215 // Process all fields
158 for k, v := range m {
216 for k, v := range m {
159 if k == "_meta" {
217 if k == "_meta" {
160 // Handle Meta field
218 // Handle Meta field
161− if meta, ok := v.(map[string]interface{}); ok {
219+ if meta, ok := v.(map[string]any); ok {
162 p.Meta = meta
220 p.Meta = meta
163 }
221 }
164 } else {
222 } else {
@@ -173,18 +231,86 @@ func (p *NotificationParams) UnmarshalJSON(data []byte) error {
173type Result struct {
231type Result struct {
174 // This result property is reserved by the protocol to allow clients and
232 // This result property is reserved by the protocol to allow clients and
175 // servers to attach additional metadata to their responses.
233 // servers to attach additional metadata to their responses.
176− Meta map[string]interface{} `json:"_meta,omitempty"`
234+ Meta map[string]any `json:"_meta,omitempty"`
177}
235}
178
236
179// RequestId is a uniquely identifying ID for a request in JSON-RPC.
237// RequestId is a uniquely identifying ID for a request in JSON-RPC.
180// It can be any JSON-serializable value, typically a number or string.
238// It can be any JSON-serializable value, typically a number or string.
181−type RequestId interface{}
239+type RequestId struct {
240+ value any
241+}
242+
243+// NewRequestId creates a new RequestId with the given value
244+func NewRequestId(value any) RequestId {
245+ return RequestId{value: value}
246+}
247+
248+// Value returns the underlying value of the RequestId
249+func (r RequestId) Value() any {
250+ return r.value
251+}
252+
253+// String returns a string representation of the RequestId
254+func (r RequestId) String() string {
255+ switch v := r.value.(type) {
256+ case string:
257+ return "string:" + v
258+ case int64:
259+ return "int64:" + strconv.FormatInt(v, 10)
260+ case float64:
261+ if v == float64(int64(v)) {
262+ return "int64:" + strconv.FormatInt(int64(v), 10)
263+ }
264+ return "float64:" + strconv.FormatFloat(v, 'f', -1, 64)
265+ case nil:
266+ return "<nil>"
267+ default:
268+ return "unknown:" + fmt.Sprintf("%v", v)
269+ }
270+}
271+
272+// IsNil returns true if the RequestId is nil
273+func (r RequestId) IsNil() bool {
274+ return r.value == nil
275+}
276+
277+func (r RequestId) MarshalJSON() ([]byte, error) {
278+ return json.Marshal(r.value)
279+}
280+
281+func (r *RequestId) UnmarshalJSON(data []byte) error {
282+
283+ if string(data) == "null" {
284+ r.value = nil
285+ return nil
286+ }
287+
288+ // Try unmarshaling as string first
289+ var s string
290+ if err := json.Unmarshal(data, &s); err == nil {
291+ r.value = s
292+ return nil
293+ }
294+
295+ // JSON numbers are unmarshaled as float64 in Go
296+ var f float64
297+ if err := json.Unmarshal(data, &f); err == nil {
298+ if f == float64(int64(f)) {
299+ r.value = int64(f)
300+ } else {
301+ r.value = f
302+ }
303+ return nil
304+ }
305+
306+ return fmt.Errorf("invalid request id: %s", string(data))
307+}
182
308
183// JSONRPCRequest represents a request that expects a response.
309// JSONRPCRequest represents a request that expects a response.
184type JSONRPCRequest struct {
310type JSONRPCRequest struct {
185− JSONRPC string `json:"jsonrpc"`
311+ JSONRPC string `json:"jsonrpc"`
186− ID RequestId `json:"id"`
312+ ID RequestId `json:"id"`
187− Params interface{} `json:"params,omitempty"`
313+ Params any `json:"params,omitempty"`
188 Request
314 Request
189}
315}
190
316
@@ -196,9 +322,9 @@ type JSONRPCNotification struct {
196
322
197// JSONRPCResponse represents a successful (non-error) response to a request.
323// JSONRPCResponse represents a successful (non-error) response to a request.
198type JSONRPCResponse struct {
324type JSONRPCResponse struct {
199− JSONRPC string `json:"jsonrpc"`
325+ JSONRPC string `json:"jsonrpc"`
200− ID RequestId `json:"id"`
326+ ID RequestId `json:"id"`
201− Result interface{} `json:"result"`
327+ Result any `json:"result"`
202}
328}
203
329
204// JSONRPCError represents a non-successful (error) response to a request.
330// JSONRPCError represents a non-successful (error) response to a request.
@@ -213,7 +339,7 @@ type JSONRPCError struct {
213 Message string `json:"message"`
339 Message string `json:"message"`
214 // Additional information about the error. The value of this member
340 // Additional information about the error. The value of this member
215 // is defined by the sender (e.g. detailed error information, nested errors etc.).
341 // is defined by the sender (e.g. detailed error information, nested errors etc.).
216− Data interface{} `json:"data,omitempty"`
342+ Data any `json:"data,omitempty"`
217 } `json:"error"`
343 } `json:"error"`
218}
344}
219
345
@@ -226,6 +352,11 @@ const (
226 INTERNAL_ERROR = -32603
352 INTERNAL_ERROR = -32603
227)
353)
228
354
355+// MCP error codes
356+const (
357+ RESOURCE_NOT_FOUND = -32002
358+)
359+
229/* Empty result */
360/* Empty result */
230
361
231// EmptyResult represents a response that indicates success but carries no data.
362// EmptyResult represents a response that indicates success but carries no data.
@@ -246,17 +377,19 @@ type EmptyResult Result
246// A client MUST NOT attempt to cancel its `initialize` request.
377// A client MUST NOT attempt to cancel its `initialize` request.
247type CancelledNotification struct {
378type CancelledNotification struct {
248 Notification
379 Notification
249− Params struct {
380+ Params CancelledNotificationParams `json:"params"`
381+}
382+
383+type CancelledNotificationParams struct {
250− // The ID of the request to cancel.
384+ // The ID of the request to cancel.
251− //
385+ //
252− // This MUST correspond to the ID of a request previously issued
386+ // This MUST correspond to the ID of a request previously issued
253− // in the same direction.
387+ // in the same direction.
254− RequestId RequestId `json:"requestId"`
388+ RequestId RequestId `json:"requestId"`
255
389
256− // An optional string describing the reason for the cancellation. This MAY
390+ // An optional string describing the reason for the cancellation. This MAY
257− // be logged or presented to the user.
391+ // be logged or presented to the user.
258− Reason string `json:"reason,omitempty"`
392+ Reason string `json:"reason,omitempty"`
259− } `json:"params"`
260}
393}
261
394
262/* Initialization */
395/* Initialization */
@@ -265,13 +398,15 @@ type CancelledNotification struct {
265// connects, asking it to begin initialization.
398// connects, asking it to begin initialization.
266type InitializeRequest struct {
399type InitializeRequest struct {
267 Request
400 Request
268− Params struct {
401+ Params InitializeParams `json:"params"`
402+}
403+
404+type InitializeParams struct {
269− // The latest version of the Model Context Protocol that the client supports.
405+ // The latest version of the Model Context Protocol that the client supports.
270− // The client MAY decide to support older versions as well.
406+ // The client MAY decide to support older versions as well.
271− ProtocolVersion string `json:"protocolVersion"`
407+ ProtocolVersion string `json:"protocolVersion"`
272− Capabilities ClientCapabilities `json:"capabilities"`
408+ Capabilities ClientCapabilities `json:"capabilities"`
273− ClientInfo Implementation `json:"clientInfo"`
409+ ClientInfo Implementation `json:"clientInfo"`
274− } `json:"params"`
275}
410}
276
411
277// InitializeResult is sent after receiving an initialize request from the
412// InitializeResult is sent after receiving an initialize request from the
@@ -303,7 +438,7 @@ type InitializedNotification struct {
303// client can define its own, additional capabilities.
438// client can define its own, additional capabilities.
304type ClientCapabilities struct {
439type ClientCapabilities struct {
305 // Experimental, non-standard capabilities that the client supports.
440 // Experimental, non-standard capabilities that the client supports.
306− Experimental map[string]interface{} `json:"experimental,omitempty"`
441+ Experimental map[string]any `json:"experimental,omitempty"`
307 // Present if the client supports listing roots.
442 // Present if the client supports listing roots.
308 Roots *struct {
443 Roots *struct {
309 // Whether the client supports notifications for changes to the roots list.
444 // Whether the client supports notifications for changes to the roots list.
@@ -318,7 +453,7 @@ type ClientCapabilities struct {
318// server can define its own, additional capabilities.
453// server can define its own, additional capabilities.
319type ServerCapabilities struct {
454type ServerCapabilities struct {
320 // Experimental, non-standard capabilities that the server supports.
455 // Experimental, non-standard capabilities that the server supports.
321− Experimental map[string]interface{} `json:"experimental,omitempty"`
456+ Experimental map[string]any `json:"experimental,omitempty"`
322 // Present if the server supports sending log messages to the client.
457 // Present if the server supports sending log messages to the client.
323 Logging *struct{} `json:"logging,omitempty"`
458 Logging *struct{} `json:"logging,omitempty"`
324 // Present if the server offers any prompt templates.
459 // Present if the server offers any prompt templates.
@@ -362,27 +497,34 @@ type PingRequest struct {
362// receiver of a progress update for a long-running request.
497// receiver of a progress update for a long-running request.
363type ProgressNotification struct {
498type ProgressNotification struct {
364 Notification
499 Notification
365− Params struct {
500+ Params ProgressNotificationParams `json:"params"`
501+}
502+
503+type ProgressNotificationParams struct {
366− // The progress token which was given in the initial request, used to
504+ // The progress token which was given in the initial request, used to
367− // associate this notification with the request that is proceeding.
505+ // associate this notification with the request that is proceeding.
368− ProgressToken ProgressToken `json:"progressToken"`
506+ ProgressToken ProgressToken `json:"progressToken"`
369− // The progress thus far. This should increase every time progress is made,
507+ // The progress thus far. This should increase every time progress is made,
370− // even if the total is unknown.
508+ // even if the total is unknown.
371− Progress float64 `json:"progress"`
509+ Progress float64 `json:"progress"`
372− // Total number of items to process (or total progress required), if known.
510+ // Total number of items to process (or total progress required), if known.
373− Total float64 `json:"total,omitempty"`
511+ Total float64 `json:"total,omitempty"`
374− } `json:"params"`
512+ // Message related to progress. This should provide relevant human-readable
513+ // progress information.
514+ Message string `json:"message,omitempty"`
375}
515}
376
516
377/* Pagination */
517/* Pagination */
378
518
379type PaginatedRequest struct {
519type PaginatedRequest struct {
380 Request
520 Request
381− Params struct {
521+ Params PaginatedParams `json:"params,omitempty"`
522+}
523+
524+type PaginatedParams struct {
382− // An opaque token representing the current pagination position.
525+ // An opaque token representing the current pagination position.
383− // If provided, the server should return results starting after this cursor.
526+ // If provided, the server should return results starting after this cursor.
384− Cursor Cursor `json:"cursor,omitempty"`
527+ Cursor Cursor `json:"cursor,omitempty"`
385− } `json:"params,omitempty"`
386}
528}
387
529
388type PaginatedResult struct {
530type PaginatedResult struct {
@@ -425,13 +567,15 @@ type ListResourceTemplatesResult struct {
425// specific resource URI.
567// specific resource URI.
426type ReadResourceRequest struct {
568type ReadResourceRequest struct {
427 Request
569 Request
428− Params struct {
570+ Params ReadResourceParams `json:"params"`
571+}
572+
573+type ReadResourceParams struct {
429− // The URI of the resource to read. The URI can use any protocol; it is up
574+ // The URI of the resource to read. The URI can use any protocol; it is up
430− // to the server how to interpret it.
575+ // to the server how to interpret it.
431− URI string `json:"uri"`
576+ URI string `json:"uri"`
432− // Arguments to pass to the resource handler
577+ // Arguments to pass to the resource handler
433− Arguments map[string]interface{} `json:"arguments,omitempty"`
578+ Arguments map[string]any `json:"arguments,omitempty"`
434− } `json:"params"`
435}
579}
436
580
437// ReadResourceResult is the server's response to a resources/read request
581// ReadResourceResult is the server's response to a resources/read request
@@ -453,11 +597,13 @@ type ResourceListChangedNotification struct {
453// notifications from the server whenever a particular resource changes.
597// notifications from the server whenever a particular resource changes.
454type SubscribeRequest struct {
598type SubscribeRequest struct {
455 Request
599 Request
456− Params struct {
600+ Params SubscribeParams `json:"params"`
601+}
602+
603+type SubscribeParams struct {
457− // The URI of the resource to subscribe to. The URI can use any protocol; it
604+ // The URI of the resource to subscribe to. The URI can use any protocol; it
458− // is up to the server how to interpret it.
605+ // is up to the server how to interpret it.
459− URI string `json:"uri"`
606+ URI string `json:"uri"`
460− } `json:"params"`
461}
607}
462
608
463// UnsubscribeRequest is sent from the client to request cancellation of
609// UnsubscribeRequest is sent from the client to request cancellation of
@@ -465,10 +611,12 @@ type SubscribeRequest struct {
465// resources/subscribe request.
611// resources/subscribe request.
466type UnsubscribeRequest struct {
612type UnsubscribeRequest struct {
467 Request
613 Request
468− Params struct {
614+ Params UnsubscribeParams `json:"params"`
615+}
616+
617+type UnsubscribeParams struct {
469− // The URI of the resource to unsubscribe from.
618+ // The URI of the resource to unsubscribe from.
470− URI string `json:"uri"`
619+ URI string `json:"uri"`
471− } `json:"params"`
472}
620}
473
621
474// ResourceUpdatedNotification is a notification from the server to the client,
622// ResourceUpdatedNotification is a notification from the server to the client,
@@ -476,11 +624,12 @@ type UnsubscribeRequest struct {
476// should only be sent if the client previously sent a resources/subscribe request.
624// should only be sent if the client previously sent a resources/subscribe request.
477type ResourceUpdatedNotification struct {
625type ResourceUpdatedNotification struct {
478 Notification
626 Notification
479− Params struct {
627+ Params ResourceUpdatedNotificationParams `json:"params"`
628+}
629+type ResourceUpdatedNotificationParams struct {
480− // The URI of the resource that has been updated. This might be a sub-
630+ // The URI of the resource that has been updated. This might be a sub-
481− // resource of the one that the client actually subscribed to.
631+ // resource of the one that the client actually subscribed to.
482− URI string `json:"uri"`
632+ URI string `json:"uri"`
483− } `json:"params"`
484}
633}
485
634
486// Resource represents a known resource that the server is capable of reading.
635// Resource represents a known resource that the server is capable of reading.
@@ -501,6 +650,11 @@ type Resource struct {
501 MIMEType string `json:"mimeType,omitempty"`
650 MIMEType string `json:"mimeType,omitempty"`
502}
651}
503
652
653+// GetName returns the name of the resource.
654+func (r Resource) GetName() string {
655+ return r.Name
656+}
657+
504// ResourceTemplate represents a template description for resources available
658// ResourceTemplate represents a template description for resources available
505// on the server.
659// on the server.
506type ResourceTemplate struct {
660type ResourceTemplate struct {
@@ -522,6 +676,11 @@ type ResourceTemplate struct {
522 MIMEType string `json:"mimeType,omitempty"`
676 MIMEType string `json:"mimeType,omitempty"`
523}
677}
524
678
679+// GetName returns the name of the resourceTemplate.
680+func (rt ResourceTemplate) GetName() string {
681+ return rt.Name
682+}
683+
525// ResourceContents represents the contents of a specific resource or sub-
684// ResourceContents represents the contents of a specific resource or sub-
526// resource.
685// resource.
527type ResourceContents interface {
686type ResourceContents interface {
@@ -557,12 +716,14 @@ func (BlobResourceContents) isResourceContents() {}
557// adjust logging.
716// adjust logging.
558type SetLevelRequest struct {
717type SetLevelRequest struct {
559 Request
718 Request
560− Params struct {
719+ Params SetLevelParams `json:"params"`
720+}
721+
722+type SetLevelParams struct {
561− // The level of logging that the client wants to receive from the server.
723+ // The level of logging that the client wants to receive from the server.
562− // The server should send all logs at this level and higher (i.e., more severe) to
724+ // The server should send all logs at this level and higher (i.e., more severe) to
563− // the client as notifications/logging/message.
725+ // the client as notifications/logging/message.
564− Level LoggingLevel `json:"level"`
726+ Level LoggingLevel `json:"level"`
565− } `json:"params"`
566}
727}
567
728
568// LoggingMessageNotification is a notification of a log message passed from
729// LoggingMessageNotification is a notification of a log message passed from
@@ -570,15 +731,17 @@ type SetLevelRequest struct {
570// the server MAY decide which messages to send automatically.
731// the server MAY decide which messages to send automatically.
571type LoggingMessageNotification struct {
732type LoggingMessageNotification struct {
572 Notification
733 Notification
573− Params struct {
734+ Params LoggingMessageNotificationParams `json:"params"`
735+}
736+
737+type LoggingMessageNotificationParams struct {
574− // The severity of this log message.
738+ // The severity of this log message.
575− Level LoggingLevel `json:"level"`
739+ Level LoggingLevel `json:"level"`
576− // An optional name of the logger issuing this message.
740+ // An optional name of the logger issuing this message.
577− Logger string `json:"logger,omitempty"`
741+ Logger string `json:"logger,omitempty"`
578− // The data to be logged, such as a string message or an object. Any JSON
742+ // The data to be logged, such as a string message or an object. Any JSON
579− // serializable type is allowed here.
743+ // serializable type is allowed here.
580− Data interface{} `json:"data"`
744+ Data any `json:"data"`
581− } `json:"params"`
582}
745}
583
746
584// LoggingLevel represents the severity of a log message.
747// LoggingLevel represents the severity of a log message.
@@ -606,16 +769,18 @@ const (
606// the request (human in the loop) and decide whether to approve it.
769// the request (human in the loop) and decide whether to approve it.
607type CreateMessageRequest struct {
770type CreateMessageRequest struct {
608 Request
771 Request
609− Params struct {
772+ CreateMessageParams `json:"params"`
773+}
774+
775+type CreateMessageParams struct {
610− Messages []SamplingMessage `json:"messages"`
776+ Messages []SamplingMessage `json:"messages"`
611− ModelPreferences *ModelPreferences `json:"modelPreferences,omitempty"`
777+ ModelPreferences *ModelPreferences `json:"modelPreferences,omitempty"`
612− SystemPrompt string `json:"systemPrompt,omitempty"`
778+ SystemPrompt string `json:"systemPrompt,omitempty"`
613− IncludeContext string `json:"includeContext,omitempty"`
779+ IncludeContext string `json:"includeContext,omitempty"`
614− Temperature float64 `json:"temperature,omitempty"`
780+ Temperature float64 `json:"temperature,omitempty"`
615− MaxTokens int `json:"maxTokens"`
781+ MaxTokens int `json:"maxTokens"`
616− StopSequences []string `json:"stopSequences,omitempty"`
782+ StopSequences []string `json:"stopSequences,omitempty"`
617− Metadata interface{} `json:"metadata,omitempty"`
783+ Metadata any `json:"metadata,omitempty"`
618− } `json:"params"`
619}
784}
620
785
621// CreateMessageResult is the client's response to a sampling/create_message
786// CreateMessageResult is the client's response to a sampling/create_message
@@ -633,28 +798,30 @@ type CreateMessageResult struct {
633
798
634// SamplingMessage describes a message issued to or received from an LLM API.
799// SamplingMessage describes a message issued to or received from an LLM API.
635type SamplingMessage struct {
800type SamplingMessage struct {
636− Role Role `json:"role"`
801+ Role Role `json:"role"`
637− Content interface{} `json:"content"` // Can be TextContent or ImageContent
802+ Content any `json:"content"` // Can be TextContent, ImageContent or AudioContent
803+}
804+
805+type Annotations struct {
806+ // Describes who the intended customer of this object or data is.
807+ //
808+ // It can include multiple entries to indicate content useful for multiple
809+ // audiences (e.g., `["user", "assistant"]`).
810+ Audience []Role `json:"audience,omitempty"`
811+
812+ // Describes how important this data is for operating the server.
813+ //
814+ // A value of 1 means "most important," and indicates that the data is
815+ // effectively required, while 0 means "least important," and indicates that
816+ // the data is entirely optional.
817+ Priority float64 `json:"priority,omitempty"`
638}
818}
639
819
640// Annotated is the base for objects that include optional annotations for the
820// Annotated is the base for objects that include optional annotations for the
641// client. The client can use annotations to inform how objects are used or
821// client. The client can use annotations to inform how objects are used or
642// displayed
822// displayed
643type Annotated struct {
823type Annotated struct {
644− Annotations *struct {
645− // Describes who the intended customer of this object or data is.
646− //
647− // It can include multiple entries to indicate content useful for multiple
648− // audiences (e.g., `["user", "assistant"]`).
649− Audience []Role `json:"audience,omitempty"`
650−
651− // Describes how important this data is for operating the server.
652− //
653− // A value of 1 means "most important," and indicates that the data is
654− // effectively required, while 0 means "least important," and indicates that
655− // the data is entirely optional.
656− Priority float64 `json:"priority,omitempty"`
657− } `json:"annotations,omitempty"`
824+ Annotations *Annotations `json:"annotations,omitempty"`
658}
825}
659
826
660type Content interface {
827type Content interface {
@@ -685,6 +852,19 @@ type ImageContent struct {
685
852
686func (ImageContent) isContent() {}
853func (ImageContent) isContent() {}
687
854
855+// AudioContent represents the contents of audio, embedded into a prompt or tool call result.
856+// It must have Type set to "audio".
857+type AudioContent struct {
858+ Annotated
859+ Type string `json:"type"` // Must be "audio"
860+ // The base64-encoded audio data.
861+ Data string `json:"data"`
862+ // The MIME type of the audio. Different providers may support different audio types.
863+ MIMEType string `json:"mimeType"`
864+}
865+
866+func (AudioContent) isContent() {}
867+
688// EmbeddedResource represents the contents of a resource, embedded into a prompt or tool call result.
868// EmbeddedResource represents the contents of a resource, embedded into a prompt or tool call result.
689//
869//
690// It is up to the client how best to render embedded resources for the
870// It is up to the client how best to render embedded resources for the
@@ -758,15 +938,17 @@ type ModelHint struct {
758// CompleteRequest is a request from the client to the server, to ask for completion options.
938// CompleteRequest is a request from the client to the server, to ask for completion options.
759type CompleteRequest struct {
939type CompleteRequest struct {
760 Request
940 Request
761− Params struct {
941+ Params CompleteParams `json:"params"`
942+}
943+
944+type CompleteParams struct {
762− Ref interface{} `json:"ref"` // Can be PromptReference or ResourceReference
945+ Ref any `json:"ref"` // Can be PromptReference or ResourceReference
763− Argument struct {
946+ Argument struct {
764− // The name of the argument
947+ // The name of the argument
765− Name string `json:"name"`
948+ Name string `json:"name"`
766− // The value of the argument to use for completion matching.
949+ // The value of the argument to use for completion matching.
767− Value string `json:"value"`
950+ Value string `json:"value"`
768− } `json:"argument"`
951+ } `json:"argument"`
769− } `json:"params"`
770}
952}
771
953
772// CompleteResult is the server's response to a completion/complete request
954// CompleteResult is the server's response to a completion/complete request
@@ -839,22 +1021,24 @@ type RootsListChangedNotification struct {
839 Notification
1021 Notification
840}
1022}
841
1023
842−/* Client messages */
843// ClientRequest represents any request that can be sent from client to server.
1024// ClientRequest represents any request that can be sent from client to server.
844−type ClientRequest interface{}
1025+type ClientRequest any
845
1026
846// ClientNotification represents any notification that can be sent from client to server.
1027// ClientNotification represents any notification that can be sent from client to server.
847−type ClientNotification interface{}
1028+type ClientNotification any
848
1029
849// ClientResult represents any result that can be sent from client to server.
1030// ClientResult represents any result that can be sent from client to server.
850−type ClientResult interface{}
1031+type ClientResult any
851
1032
852−/* Server messages */
853// ServerRequest represents any request that can be sent from server to client.
1033// ServerRequest represents any request that can be sent from server to client.
854−type ServerRequest interface{}
1034+type ServerRequest any
855
1035
856// ServerNotification represents any notification that can be sent from server to client.
1036// ServerNotification represents any notification that can be sent from server to client.
857−type ServerNotification interface{}
1037+type ServerNotification any
858
1038
859// ServerResult represents any result that can be sent from server to client.
1039// ServerResult represents any result that can be sent from server to client.
860−type ServerResult interface{}
1040+type ServerResult any
1041+
1042+type Named interface {
1043+ GetName() string
1044+}
vendor/github.com/mark3labs/mcp-go/mcp/utils.go+231−15
@@ -3,6 +3,8 @@ package mcp
3import (
3import (
4 "encoding/json"
4 "encoding/json"
5 "fmt"
5 "fmt"
6+
7+ "github.com/spf13/cast"
6)
8)
7
9
8// ClientRequest types
10// ClientRequest types
@@ -58,7 +60,7 @@ var _ ServerResult = &ListToolsResult{}
58// Helper functions for type assertions
60// Helper functions for type assertions
59
61
60// asType attempts to cast the given interface to the given type
62// asType attempts to cast the given interface to the given type
61−func asType[T any](content interface{}) (*T, bool) {
63+func asType[T any](content any) (*T, bool) {
62 tc, ok := content.(T)
64 tc, ok := content.(T)
63 if !ok {
65 if !ok {
64 return nil, false
66 return nil, false
@@ -67,27 +69,32 @@ func asType[T any](content interface{}) (*T, bool) {
67}
69}
68
70
69// AsTextContent attempts to cast the given interface to TextContent
71// AsTextContent attempts to cast the given interface to TextContent
70−func AsTextContent(content interface{}) (*TextContent, bool) {
72+func AsTextContent(content any) (*TextContent, bool) {
71 return asType[TextContent](content)
73 return asType[TextContent](content)
72}
74}
73
75
74// AsImageContent attempts to cast the given interface to ImageContent
76// AsImageContent attempts to cast the given interface to ImageContent
75−func AsImageContent(content interface{}) (*ImageContent, bool) {
77+func AsImageContent(content any) (*ImageContent, bool) {
76 return asType[ImageContent](content)
78 return asType[ImageContent](content)
77}
79}
78
80
81+// AsAudioContent attempts to cast the given interface to AudioContent
82+func AsAudioContent(content any) (*AudioContent, bool) {
83+ return asType[AudioContent](content)
84+}
85+
79// AsEmbeddedResource attempts to cast the given interface to EmbeddedResource
86// AsEmbeddedResource attempts to cast the given interface to EmbeddedResource
80−func AsEmbeddedResource(content interface{}) (*EmbeddedResource, bool) {
87+func AsEmbeddedResource(content any) (*EmbeddedResource, bool) {
81 return asType[EmbeddedResource](content)
88 return asType[EmbeddedResource](content)
82}
89}
83
90
84// AsTextResourceContents attempts to cast the given interface to TextResourceContents
91// AsTextResourceContents attempts to cast the given interface to TextResourceContents
85−func AsTextResourceContents(content interface{}) (*TextResourceContents, bool) {
92+func AsTextResourceContents(content any) (*TextResourceContents, bool) {
86 return asType[TextResourceContents](content)
93 return asType[TextResourceContents](content)
87}
94}
88
95
89// AsBlobResourceContents attempts to cast the given interface to BlobResourceContents
96// AsBlobResourceContents attempts to cast the given interface to BlobResourceContents
90−func AsBlobResourceContents(content interface{}) (*BlobResourceContents, bool) {
97+func AsBlobResourceContents(content any) (*BlobResourceContents, bool) {
91 return asType[BlobResourceContents](content)
98 return asType[BlobResourceContents](content)
92}
99}
93
100
@@ -107,15 +114,15 @@ func NewJSONRPCError(
107 id RequestId,
114 id RequestId,
108 code int,
115 code int,
109 message string,
116 message string,
110− data interface{},
117+ data any,
111) JSONRPCError {
118) JSONRPCError {
112 return JSONRPCError{
119 return JSONRPCError{
113 JSONRPC: JSONRPC_VERSION,
120 JSONRPC: JSONRPC_VERSION,
114 ID: id,
121 ID: id,
115 Error: struct {
122 Error: struct {
116− Code int `json:"code"`
123+ Code int `json:"code"`
117− Message string `json:"message"`
124+ Message string `json:"message"`
118− Data interface{} `json:"data,omitempty"`
125+ Data any `json:"data,omitempty"`
119 }{
126 }{
120 Code: code,
127 Code: code,
121 Message: message,
128 Message: message,
@@ -124,11 +131,13 @@ func NewJSONRPCError(
124 }
131 }
125}
132}
126
133
134+// NewProgressNotification
127// Helper function for creating a progress notification
135// Helper function for creating a progress notification
128func NewProgressNotification(
136func NewProgressNotification(
129 token ProgressToken,
137 token ProgressToken,
130 progress float64,
138 progress float64,
131 total *float64,
139 total *float64,
140+ message *string,
132) ProgressNotification {
141) ProgressNotification {
133 notification := ProgressNotification{
142 notification := ProgressNotification{
134 Notification: Notification{
143 Notification: Notification{
@@ -138,6 +147,7 @@ func NewProgressNotification(
138 ProgressToken ProgressToken `json:"progressToken"`
147 ProgressToken ProgressToken `json:"progressToken"`
139 Progress float64 `json:"progress"`
148 Progress float64 `json:"progress"`
140 Total float64 `json:"total,omitempty"`
149 Total float64 `json:"total,omitempty"`
150+ Message string `json:"message,omitempty"`
141 }{
151 }{
142 ProgressToken: token,
152 ProgressToken: token,
143 Progress: progress,
153 Progress: progress,
@@ -146,14 +156,18 @@ func NewProgressNotification(
146 if total != nil {
156 if total != nil {
147 notification.Params.Total = *total
157 notification.Params.Total = *total
148 }
158 }
159+ if message != nil {
160+ notification.Params.Message = *message
161+ }
149 return notification
162 return notification
150}
163}
151
164
165+// NewLoggingMessageNotification
152// Helper function for creating a logging message notification
166// Helper function for creating a logging message notification
153func NewLoggingMessageNotification(
167func NewLoggingMessageNotification(
154 level LoggingLevel,
168 level LoggingLevel,
155 logger string,
169 logger string,
156− data interface{},
170+ data any,
157) LoggingMessageNotification {
171) LoggingMessageNotification {
158 return LoggingMessageNotification{
172 return LoggingMessageNotification{
159 Notification: Notification{
173 Notification: Notification{
@@ -162,7 +176,7 @@ func NewLoggingMessageNotification(
162 Params: struct {
176 Params: struct {
163 Level LoggingLevel `json:"level"`
177 Level LoggingLevel `json:"level"`
164 Logger string `json:"logger,omitempty"`
178 Logger string `json:"logger,omitempty"`
165− Data interface{} `json:"data"`
179+ Data any `json:"data"`
166 }{
180 }{
167 Level: level,
181 Level: level,
168 Logger: logger,
182 Logger: logger,
@@ -171,6 +185,7 @@ func NewLoggingMessageNotification(
171 }
185 }
172}
186}
173
187
188+// NewPromptMessage
174// Helper function to create a new PromptMessage
189// Helper function to create a new PromptMessage
175func NewPromptMessage(role Role, content Content) PromptMessage {
190func NewPromptMessage(role Role, content Content) PromptMessage {
176 return PromptMessage{
191 return PromptMessage{
@@ -179,6 +194,7 @@ func NewPromptMessage(role Role, content Content) PromptMessage {
179 }
194 }
180}
195}
181
196
197+// NewTextContent
182// Helper function to create a new TextContent
198// Helper function to create a new TextContent
183func NewTextContent(text string) TextContent {
199func NewTextContent(text string) TextContent {
184 return TextContent{
200 return TextContent{
@@ -187,6 +203,7 @@ func NewTextContent(text string) TextContent {
187 }
203 }
188}
204}
189
205
206+// NewImageContent
190// Helper function to create a new ImageContent
207// Helper function to create a new ImageContent
191func NewImageContent(data, mimeType string) ImageContent {
208func NewImageContent(data, mimeType string) ImageContent {
192 return ImageContent{
209 return ImageContent{
@@ -196,6 +213,15 @@ func NewImageContent(data, mimeType string) ImageContent {
196 }
213 }
197}
214}
198
215
216+// Helper function to create a new AudioContent
217+func NewAudioContent(data, mimeType string) AudioContent {
218+ return AudioContent{
219+ Type: "audio",
220+ Data: data,
221+ MIMEType: mimeType,
222+ }
223+}
224+
199// Helper function to create a new EmbeddedResource
225// Helper function to create a new EmbeddedResource
200func NewEmbeddedResource(resource ResourceContents) EmbeddedResource {
226func NewEmbeddedResource(resource ResourceContents) EmbeddedResource {
201 return EmbeddedResource{
227 return EmbeddedResource{
@@ -233,6 +259,23 @@ func NewToolResultImage(text, imageData, mimeType string) *CallToolResult {
233 }
259 }
234}
260}
235
261
262+// NewToolResultAudio creates a new CallToolResult with both text and audio content
263+func NewToolResultAudio(text, imageData, mimeType string) *CallToolResult {
264+ return &CallToolResult{
265+ Content: []Content{
266+ TextContent{
267+ Type: "text",
268+ Text: text,
269+ },
270+ AudioContent{
271+ Type: "audio",
272+ Data: imageData,
273+ MIMEType: mimeType,
274+ },
275+ },
276+ }
277+}
278+
236// NewToolResultResource creates a new CallToolResult with an embedded resource
279// NewToolResultResource creates a new CallToolResult with an embedded resource
237func NewToolResultResource(
280func NewToolResultResource(
238 text string,
281 text string,
@@ -252,6 +295,53 @@ func NewToolResultResource(
252 }
295 }
253}
296}
254
297
298+// NewToolResultError creates a new CallToolResult with an error message.
299+// Any errors that originate from the tool SHOULD be reported inside the result object.
300+func NewToolResultError(text string) *CallToolResult {
301+ return &CallToolResult{
302+ Content: []Content{
303+ TextContent{
304+ Type: "text",
305+ Text: text,
306+ },
307+ },
308+ IsError: true,
309+ }
310+}
311+
312+// NewToolResultErrorFromErr creates a new CallToolResult with an error message.
313+// If an error is provided, its details will be appended to the text message.
314+// Any errors that originate from the tool SHOULD be reported inside the result object.
315+func NewToolResultErrorFromErr(text string, err error) *CallToolResult {
316+ if err != nil {
317+ text = fmt.Sprintf("%s: %v", text, err)
318+ }
319+ return &CallToolResult{
320+ Content: []Content{
321+ TextContent{
322+ Type: "text",
323+ Text: text,
324+ },
325+ },
326+ IsError: true,
327+ }
328+}
329+
330+// NewToolResultErrorf creates a new CallToolResult with an error message.
331+// The error message is formatted using the fmt package.
332+// Any errors that originate from the tool SHOULD be reported inside the result object.
333+func NewToolResultErrorf(format string, a ...any) *CallToolResult {
334+ return &CallToolResult{
335+ Content: []Content{
336+ TextContent{
337+ Type: "text",
338+ Text: fmt.Sprintf(format, a...),
339+ },
340+ },
341+ IsError: true,
342+ }
343+}
344+
255// NewListResourcesResult creates a new ListResourcesResult
345// NewListResourcesResult creates a new ListResourcesResult
256func NewListResourcesResult(
346func NewListResourcesResult(
257 resources []Resource,
347 resources []Resource,
@@ -338,6 +428,7 @@ func NewInitializeResult(
338 }
428 }
339}
429}
340
430
431+// FormatNumberResult
341// Helper for formatting numbers in tool results
432// Helper for formatting numbers in tool results
342func FormatNumberResult(value float64) *CallToolResult {
433func FormatNumberResult(value float64) *CallToolResult {
343 return NewToolResultText(fmt.Sprintf("%.2f", value))
434 return NewToolResultText(fmt.Sprintf("%.2f", value))
@@ -367,9 +458,6 @@ func ParseContent(contentMap map[string]any) (Content, error) {
367 switch contentType {
458 switch contentType {
368 case "text":
459 case "text":
369 text := ExtractString(contentMap, "text")
460 text := ExtractString(contentMap, "text")
370− if text == "" {
371− return nil, fmt.Errorf("text is missing")
372− }
373 return NewTextContent(text), nil
461 return NewTextContent(text), nil
374
462
375 case "image":
463 case "image":
@@ -380,6 +468,14 @@ func ParseContent(contentMap map[string]any) (Content, error) {
380 }
468 }
381 return NewImageContent(data, mimeType), nil
469 return NewImageContent(data, mimeType), nil
382
470
471+ case "audio":
472+ data := ExtractString(contentMap, "data")
473+ mimeType := ExtractString(contentMap, "mimeType")
474+ if data == "" || mimeType == "" {
475+ return nil, fmt.Errorf("audio data or mimeType is missing")
476+ }
477+ return NewAudioContent(data, mimeType), nil
478+
383 case "resource":
479 case "resource":
384 resourceMap := ExtractMap(contentMap, "resource")
480 resourceMap := ExtractMap(contentMap, "resource")
385 if resourceMap == nil {
481 if resourceMap == nil {
@@ -398,6 +494,10 @@ func ParseContent(contentMap map[string]any) (Content, error) {
398}
494}
399
495
400func ParseGetPromptResult(rawMessage *json.RawMessage) (*GetPromptResult, error) {
496func ParseGetPromptResult(rawMessage *json.RawMessage) (*GetPromptResult, error) {
497+ if rawMessage == nil {
498+ return nil, fmt.Errorf("response is nil")
499+ }
500+
401 var jsonContent map[string]any
501 var jsonContent map[string]any
402 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
502 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
403 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
503 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
@@ -460,6 +560,10 @@ func ParseGetPromptResult(rawMessage *json.RawMessage) (*GetPromptResult, error)
460}
560}
461
561
462func ParseCallToolResult(rawMessage *json.RawMessage) (*CallToolResult, error) {
562func ParseCallToolResult(rawMessage *json.RawMessage) (*CallToolResult, error) {
563+ if rawMessage == nil {
564+ return nil, fmt.Errorf("response is nil")
565+ }
566+
463 var jsonContent map[string]any
567 var jsonContent map[string]any
464 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
568 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
465 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
569 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
@@ -538,6 +642,10 @@ func ParseResourceContents(contentMap map[string]any) (ResourceContents, error)
538}
642}
539
643
540func ParseReadResourceResult(rawMessage *json.RawMessage) (*ReadResourceResult, error) {
644func ParseReadResourceResult(rawMessage *json.RawMessage) (*ReadResourceResult, error) {
645+ if rawMessage == nil {
646+ return nil, fmt.Errorf("response is nil")
647+ }
648+
541 var jsonContent map[string]any
649 var jsonContent map[string]any
542 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
650 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
543 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
651 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
@@ -580,3 +688,111 @@ func ParseReadResourceResult(rawMessage *json.RawMessage) (*ReadResourceResult,
580
688
581 return &result, nil
689 return &result, nil
582}
690}
691+
692+func ParseArgument(request CallToolRequest, key string, defaultVal any) any {
693+ args := request.GetArguments()
694+ if _, ok := args[key]; !ok {
695+ return defaultVal
696+ } else {
697+ return args[key]
698+ }
699+}
700+
701+// ParseBoolean extracts and converts a boolean parameter from a CallToolRequest.
702+// If the key is not found in the Arguments map, the defaultValue is returned.
703+// The function uses cast.ToBool for conversion which handles various string representations
704+// such as "true", "yes", "1", etc.
705+func ParseBoolean(request CallToolRequest, key string, defaultValue bool) bool {
706+ v := ParseArgument(request, key, defaultValue)
707+ return cast.ToBool(v)
708+}
709+
710+// ParseInt64 extracts and converts an int64 parameter from a CallToolRequest.
711+// If the key is not found in the Arguments map, the defaultValue is returned.
712+func ParseInt64(request CallToolRequest, key string, defaultValue int64) int64 {
713+ v := ParseArgument(request, key, defaultValue)
714+ return cast.ToInt64(v)
715+}
716+
717+// ParseInt32 extracts and converts an int32 parameter from a CallToolRequest.
718+func ParseInt32(request CallToolRequest, key string, defaultValue int32) int32 {
719+ v := ParseArgument(request, key, defaultValue)
720+ return cast.ToInt32(v)
721+}
722+
723+// ParseInt16 extracts and converts an int16 parameter from a CallToolRequest.
724+func ParseInt16(request CallToolRequest, key string, defaultValue int16) int16 {
725+ v := ParseArgument(request, key, defaultValue)
726+ return cast.ToInt16(v)
727+}
728+
729+// ParseInt8 extracts and converts an int8 parameter from a CallToolRequest.
730+func ParseInt8(request CallToolRequest, key string, defaultValue int8) int8 {
731+ v := ParseArgument(request, key, defaultValue)
732+ return cast.ToInt8(v)
733+}
734+
735+// ParseInt extracts and converts an int parameter from a CallToolRequest.
736+func ParseInt(request CallToolRequest, key string, defaultValue int) int {
737+ v := ParseArgument(request, key, defaultValue)
738+ return cast.ToInt(v)
739+}
740+
741+// ParseUInt extracts and converts an uint parameter from a CallToolRequest.
742+func ParseUInt(request CallToolRequest, key string, defaultValue uint) uint {
743+ v := ParseArgument(request, key, defaultValue)
744+ return cast.ToUint(v)
745+}
746+
747+// ParseUInt64 extracts and converts an uint64 parameter from a CallToolRequest.
748+func ParseUInt64(request CallToolRequest, key string, defaultValue uint64) uint64 {
749+ v := ParseArgument(request, key, defaultValue)
750+ return cast.ToUint64(v)
751+}
752+
753+// ParseUInt32 extracts and converts an uint32 parameter from a CallToolRequest.
754+func ParseUInt32(request CallToolRequest, key string, defaultValue uint32) uint32 {
755+ v := ParseArgument(request, key, defaultValue)
756+ return cast.ToUint32(v)
757+}
758+
759+// ParseUInt16 extracts and converts an uint16 parameter from a CallToolRequest.
760+func ParseUInt16(request CallToolRequest, key string, defaultValue uint16) uint16 {
761+ v := ParseArgument(request, key, defaultValue)
762+ return cast.ToUint16(v)
763+}
764+
765+// ParseUInt8 extracts and converts an uint8 parameter from a CallToolRequest.
766+func ParseUInt8(request CallToolRequest, key string, defaultValue uint8) uint8 {
767+ v := ParseArgument(request, key, defaultValue)
768+ return cast.ToUint8(v)
769+}
770+
771+// ParseFloat32 extracts and converts a float32 parameter from a CallToolRequest.
772+func ParseFloat32(request CallToolRequest, key string, defaultValue float32) float32 {
773+ v := ParseArgument(request, key, defaultValue)
774+ return cast.ToFloat32(v)
775+}
776+
777+// ParseFloat64 extracts and converts a float64 parameter from a CallToolRequest.
778+func ParseFloat64(request CallToolRequest, key string, defaultValue float64) float64 {
779+ v := ParseArgument(request, key, defaultValue)
780+ return cast.ToFloat64(v)
781+}
782+
783+// ParseString extracts and converts a string parameter from a CallToolRequest.
784+func ParseString(request CallToolRequest, key string, defaultValue string) string {
785+ v := ParseArgument(request, key, defaultValue)
786+ return cast.ToString(v)
787+}
788+
789+// ParseStringMap extracts and converts a string map parameter from a CallToolRequest.
790+func ParseStringMap(request CallToolRequest, key string, defaultValue map[string]any) map[string]any {
791+ v := ParseArgument(request, key, defaultValue)
792+ return cast.ToStringMap(v)
793+}
794+
795+// ToBoolPtr returns a pointer to the given boolean value
796+func ToBoolPtr(b bool) *bool {
797+ return &b
798+}
vendor/github.com/mark3labs/mcp-go/server/errors.gonew file+34
@@ -0,0 +1,34 @@
1+package server
2+
3+import (
4+ "errors"
5+ "fmt"
6+)
7+
8+var (
9+ // Common server errors
10+ ErrUnsupported = errors.New("not supported")
11+ ErrResourceNotFound = errors.New("resource not found")
12+ ErrPromptNotFound = errors.New("prompt not found")
13+ ErrToolNotFound = errors.New("tool not found")
14+
15+ // Session-related errors
16+ ErrSessionNotFound = errors.New("session not found")
17+ ErrSessionExists = errors.New("session already exists")
18+ ErrSessionNotInitialized = errors.New("session not properly initialized")
19+ ErrSessionDoesNotSupportTools = errors.New("session does not support per-session tools")
20+ ErrSessionDoesNotSupportLogging = errors.New("session does not support setting logging level")
21+
22+ // Notification-related errors
23+ ErrNotificationNotInitialized = errors.New("notification channel not initialized")
24+ ErrNotificationChannelBlocked = errors.New("notification channel full or blocked")
25+)
26+
27+// ErrDynamicPathConfig is returned when attempting to use static path methods with dynamic path configuration
28+type ErrDynamicPathConfig struct {
29+ Method string
30+}
31+
32+func (e *ErrDynamicPathConfig) Error() string {
33+ return fmt.Sprintf("%s cannot be used with WithDynamicBasePath. Use dynamic path logic in your router.", e.Method)
34+}
vendor/github.com/mark3labs/mcp-go/server/hooks.gonew file+532
@@ -0,0 +1,532 @@
1+// Code generated by `go generate`. DO NOT EDIT.
2+// source: server/internal/gen/hooks.go.tmpl
3+package server
4+
5+import (
6+ "context"
7+
8+ "github.com/mark3labs/mcp-go/mcp"
9+)
10+
11+// OnRegisterSessionHookFunc is a hook that will be called when a new session is registered.
12+type OnRegisterSessionHookFunc func(ctx context.Context, session ClientSession)
13+
14+// OnUnregisterSessionHookFunc is a hook that will be called when a session is being unregistered.
15+type OnUnregisterSessionHookFunc func(ctx context.Context, session ClientSession)
16+
17+// BeforeAnyHookFunc is a function that is called after the request is
18+// parsed but before the method is called.
19+type BeforeAnyHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any)
20+
21+// OnSuccessHookFunc is a hook that will be called after the request
22+// successfully generates a result, but before the result is sent to the client.
23+type OnSuccessHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any, result any)
24+
25+// OnErrorHookFunc is a hook that will be called when an error occurs,
26+// either during the request parsing or the method execution.
27+//
28+// Example usage:
29+// ```
30+//
31+// hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
32+// // Check for specific error types using errors.Is
33+// if errors.Is(err, ErrUnsupported) {
34+// // Handle capability not supported errors
35+// log.Printf("Capability not supported: %v", err)
36+// }
37+//
38+// // Use errors.As to get specific error types
39+// var parseErr = &UnparsableMessageError{}
40+// if errors.As(err, &parseErr) {
41+// // Access specific methods/fields of the error type
42+// log.Printf("Failed to parse message for method %s: %v",
43+// parseErr.GetMethod(), parseErr.Unwrap())
44+// // Access the raw message that failed to parse
45+// rawMsg := parseErr.GetMessage()
46+// }
47+//
48+// // Check for specific resource/prompt/tool errors
49+// switch {
50+// case errors.Is(err, ErrResourceNotFound):
51+// log.Printf("Resource not found: %v", err)
52+// case errors.Is(err, ErrPromptNotFound):
53+// log.Printf("Prompt not found: %v", err)
54+// case errors.Is(err, ErrToolNotFound):
55+// log.Printf("Tool not found: %v", err)
56+// }
57+// })
58+type OnErrorHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error)
59+
60+// OnRequestInitializationFunc is a function that called before handle diff request method
61+// Should any errors arise during func execution, the service will promptly return the corresponding error message.
62+type OnRequestInitializationFunc func(ctx context.Context, id any, message any) error
63+
64+type OnBeforeInitializeFunc func(ctx context.Context, id any, message *mcp.InitializeRequest)
65+type OnAfterInitializeFunc func(ctx context.Context, id any, message *mcp.InitializeRequest, result *mcp.InitializeResult)
66+
67+type OnBeforePingFunc func(ctx context.Context, id any, message *mcp.PingRequest)
68+type OnAfterPingFunc func(ctx context.Context, id any, message *mcp.PingRequest, result *mcp.EmptyResult)
69+
70+type OnBeforeSetLevelFunc func(ctx context.Context, id any, message *mcp.SetLevelRequest)
71+type OnAfterSetLevelFunc func(ctx context.Context, id any, message *mcp.SetLevelRequest, result *mcp.EmptyResult)
72+
73+type OnBeforeListResourcesFunc func(ctx context.Context, id any, message *mcp.ListResourcesRequest)
74+type OnAfterListResourcesFunc func(ctx context.Context, id any, message *mcp.ListResourcesRequest, result *mcp.ListResourcesResult)
75+
76+type OnBeforeListResourceTemplatesFunc func(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest)
77+type OnAfterListResourceTemplatesFunc func(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest, result *mcp.ListResourceTemplatesResult)
78+
79+type OnBeforeReadResourceFunc func(ctx context.Context, id any, message *mcp.ReadResourceRequest)
80+type OnAfterReadResourceFunc func(ctx context.Context, id any, message *mcp.ReadResourceRequest, result *mcp.ReadResourceResult)
81+
82+type OnBeforeListPromptsFunc func(ctx context.Context, id any, message *mcp.ListPromptsRequest)
83+type OnAfterListPromptsFunc func(ctx context.Context, id any, message *mcp.ListPromptsRequest, result *mcp.ListPromptsResult)
84+
85+type OnBeforeGetPromptFunc func(ctx context.Context, id any, message *mcp.GetPromptRequest)
86+type OnAfterGetPromptFunc func(ctx context.Context, id any, message *mcp.GetPromptRequest, result *mcp.GetPromptResult)
87+
88+type OnBeforeListToolsFunc func(ctx context.Context, id any, message *mcp.ListToolsRequest)
89+type OnAfterListToolsFunc func(ctx context.Context, id any, message *mcp.ListToolsRequest, result *mcp.ListToolsResult)
90+
91+type OnBeforeCallToolFunc func(ctx context.Context, id any, message *mcp.CallToolRequest)
92+type OnAfterCallToolFunc func(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult)
93+
94+type Hooks struct {
95+ OnRegisterSession []OnRegisterSessionHookFunc
96+ OnUnregisterSession []OnUnregisterSessionHookFunc
97+ OnBeforeAny []BeforeAnyHookFunc
98+ OnSuccess []OnSuccessHookFunc
99+ OnError []OnErrorHookFunc
100+ OnRequestInitialization []OnRequestInitializationFunc
101+ OnBeforeInitialize []OnBeforeInitializeFunc
102+ OnAfterInitialize []OnAfterInitializeFunc
103+ OnBeforePing []OnBeforePingFunc
104+ OnAfterPing []OnAfterPingFunc
105+ OnBeforeSetLevel []OnBeforeSetLevelFunc
106+ OnAfterSetLevel []OnAfterSetLevelFunc
107+ OnBeforeListResources []OnBeforeListResourcesFunc
108+ OnAfterListResources []OnAfterListResourcesFunc
109+ OnBeforeListResourceTemplates []OnBeforeListResourceTemplatesFunc
110+ OnAfterListResourceTemplates []OnAfterListResourceTemplatesFunc
111+ OnBeforeReadResource []OnBeforeReadResourceFunc
112+ OnAfterReadResource []OnAfterReadResourceFunc
113+ OnBeforeListPrompts []OnBeforeListPromptsFunc
114+ OnAfterListPrompts []OnAfterListPromptsFunc
115+ OnBeforeGetPrompt []OnBeforeGetPromptFunc
116+ OnAfterGetPrompt []OnAfterGetPromptFunc
117+ OnBeforeListTools []OnBeforeListToolsFunc
118+ OnAfterListTools []OnAfterListToolsFunc
119+ OnBeforeCallTool []OnBeforeCallToolFunc
120+ OnAfterCallTool []OnAfterCallToolFunc
121+}
122+
123+func (c *Hooks) AddBeforeAny(hook BeforeAnyHookFunc) {
124+ c.OnBeforeAny = append(c.OnBeforeAny, hook)
125+}
126+
127+func (c *Hooks) AddOnSuccess(hook OnSuccessHookFunc) {
128+ c.OnSuccess = append(c.OnSuccess, hook)
129+}
130+
131+// AddOnError registers a hook function that will be called when an error occurs.
132+// The error parameter contains the actual error object, which can be interrogated
133+// using Go's error handling patterns like errors.Is and errors.As.
134+//
135+// Example:
136+// ```
137+// // Create a channel to receive errors for testing
138+// errChan := make(chan error, 1)
139+//
140+// // Register hook to capture and inspect errors
141+// hooks := &Hooks{}
142+//
143+// hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
144+// // For capability-related errors
145+// if errors.Is(err, ErrUnsupported) {
146+// // Handle capability not supported
147+// errChan <- err
148+// return
149+// }
150+//
151+// // For parsing errors
152+// var parseErr = &UnparsableMessageError{}
153+// if errors.As(err, &parseErr) {
154+// // Handle unparsable message errors
155+// fmt.Printf("Failed to parse %s request: %v\n",
156+// parseErr.GetMethod(), parseErr.Unwrap())
157+// errChan <- parseErr
158+// return
159+// }
160+//
161+// // For resource/prompt/tool not found errors
162+// if errors.Is(err, ErrResourceNotFound) ||
163+// errors.Is(err, ErrPromptNotFound) ||
164+// errors.Is(err, ErrToolNotFound) {
165+// // Handle not found errors
166+// errChan <- err
167+// return
168+// }
169+//
170+// // For other errors
171+// errChan <- err
172+// })
173+//
174+// server := NewMCPServer("test-server", "1.0.0", WithHooks(hooks))
175+// ```
176+func (c *Hooks) AddOnError(hook OnErrorHookFunc) {
177+ c.OnError = append(c.OnError, hook)
178+}
179+
180+func (c *Hooks) beforeAny(ctx context.Context, id any, method mcp.MCPMethod, message any) {
181+ if c == nil {
182+ return
183+ }
184+ for _, hook := range c.OnBeforeAny {
185+ hook(ctx, id, method, message)
186+ }
187+}
188+
189+func (c *Hooks) onSuccess(ctx context.Context, id any, method mcp.MCPMethod, message any, result any) {
190+ if c == nil {
191+ return
192+ }
193+ for _, hook := range c.OnSuccess {
194+ hook(ctx, id, method, message, result)
195+ }
196+}
197+
198+// onError calls all registered error hooks with the error object.
199+// The err parameter contains the actual error that occurred, which implements
200+// the standard error interface and may be a wrapped error or custom error type.
201+//
202+// This allows consumer code to use Go's error handling patterns:
203+// - errors.Is(err, ErrUnsupported) to check for specific sentinel errors
204+// - errors.As(err, &customErr) to extract custom error types
205+//
206+// Common error types include:
207+// - ErrUnsupported: When a capability is not enabled
208+// - UnparsableMessageError: When request parsing fails
209+// - ErrResourceNotFound: When a resource is not found
210+// - ErrPromptNotFound: When a prompt is not found
211+// - ErrToolNotFound: When a tool is not found
212+func (c *Hooks) onError(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
213+ if c == nil {
214+ return
215+ }
216+ for _, hook := range c.OnError {
217+ hook(ctx, id, method, message, err)
218+ }
219+}
220+
221+func (c *Hooks) AddOnRegisterSession(hook OnRegisterSessionHookFunc) {
222+ c.OnRegisterSession = append(c.OnRegisterSession, hook)
223+}
224+
225+func (c *Hooks) RegisterSession(ctx context.Context, session ClientSession) {
226+ if c == nil {
227+ return
228+ }
229+ for _, hook := range c.OnRegisterSession {
230+ hook(ctx, session)
231+ }
232+}
233+
234+func (c *Hooks) AddOnUnregisterSession(hook OnUnregisterSessionHookFunc) {
235+ c.OnUnregisterSession = append(c.OnUnregisterSession, hook)
236+}
237+
238+func (c *Hooks) UnregisterSession(ctx context.Context, session ClientSession) {
239+ if c == nil {
240+ return
241+ }
242+ for _, hook := range c.OnUnregisterSession {
243+ hook(ctx, session)
244+ }
245+}
246+
247+func (c *Hooks) AddOnRequestInitialization(hook OnRequestInitializationFunc) {
248+ c.OnRequestInitialization = append(c.OnRequestInitialization, hook)
249+}
250+
251+func (c *Hooks) onRequestInitialization(ctx context.Context, id any, message any) error {
252+ if c == nil {
253+ return nil
254+ }
255+ for _, hook := range c.OnRequestInitialization {
256+ err := hook(ctx, id, message)
257+ if err != nil {
258+ return err
259+ }
260+ }
261+ return nil
262+}
263+func (c *Hooks) AddBeforeInitialize(hook OnBeforeInitializeFunc) {
264+ c.OnBeforeInitialize = append(c.OnBeforeInitialize, hook)
265+}
266+
267+func (c *Hooks) AddAfterInitialize(hook OnAfterInitializeFunc) {
268+ c.OnAfterInitialize = append(c.OnAfterInitialize, hook)
269+}
270+
271+func (c *Hooks) beforeInitialize(ctx context.Context, id any, message *mcp.InitializeRequest) {
272+ c.beforeAny(ctx, id, mcp.MethodInitialize, message)
273+ if c == nil {
274+ return
275+ }
276+ for _, hook := range c.OnBeforeInitialize {
277+ hook(ctx, id, message)
278+ }
279+}
280+
281+func (c *Hooks) afterInitialize(ctx context.Context, id any, message *mcp.InitializeRequest, result *mcp.InitializeResult) {
282+ c.onSuccess(ctx, id, mcp.MethodInitialize, message, result)
283+ if c == nil {
284+ return
285+ }
286+ for _, hook := range c.OnAfterInitialize {
287+ hook(ctx, id, message, result)
288+ }
289+}
290+func (c *Hooks) AddBeforePing(hook OnBeforePingFunc) {
291+ c.OnBeforePing = append(c.OnBeforePing, hook)
292+}
293+
294+func (c *Hooks) AddAfterPing(hook OnAfterPingFunc) {
295+ c.OnAfterPing = append(c.OnAfterPing, hook)
296+}
297+
298+func (c *Hooks) beforePing(ctx context.Context, id any, message *mcp.PingRequest) {
299+ c.beforeAny(ctx, id, mcp.MethodPing, message)
300+ if c == nil {
301+ return
302+ }
303+ for _, hook := range c.OnBeforePing {
304+ hook(ctx, id, message)
305+ }
306+}
307+
308+func (c *Hooks) afterPing(ctx context.Context, id any, message *mcp.PingRequest, result *mcp.EmptyResult) {
309+ c.onSuccess(ctx, id, mcp.MethodPing, message, result)
310+ if c == nil {
311+ return
312+ }
313+ for _, hook := range c.OnAfterPing {
314+ hook(ctx, id, message, result)
315+ }
316+}
317+func (c *Hooks) AddBeforeSetLevel(hook OnBeforeSetLevelFunc) {
318+ c.OnBeforeSetLevel = append(c.OnBeforeSetLevel, hook)
319+}
320+
321+func (c *Hooks) AddAfterSetLevel(hook OnAfterSetLevelFunc) {
322+ c.OnAfterSetLevel = append(c.OnAfterSetLevel, hook)
323+}
324+
325+func (c *Hooks) beforeSetLevel(ctx context.Context, id any, message *mcp.SetLevelRequest) {
326+ c.beforeAny(ctx, id, mcp.MethodSetLogLevel, message)
327+ if c == nil {
328+ return
329+ }
330+ for _, hook := range c.OnBeforeSetLevel {
331+ hook(ctx, id, message)
332+ }
333+}
334+
335+func (c *Hooks) afterSetLevel(ctx context.Context, id any, message *mcp.SetLevelRequest, result *mcp.EmptyResult) {
336+ c.onSuccess(ctx, id, mcp.MethodSetLogLevel, message, result)
337+ if c == nil {
338+ return
339+ }
340+ for _, hook := range c.OnAfterSetLevel {
341+ hook(ctx, id, message, result)
342+ }
343+}
344+func (c *Hooks) AddBeforeListResources(hook OnBeforeListResourcesFunc) {
345+ c.OnBeforeListResources = append(c.OnBeforeListResources, hook)
346+}
347+
348+func (c *Hooks) AddAfterListResources(hook OnAfterListResourcesFunc) {
349+ c.OnAfterListResources = append(c.OnAfterListResources, hook)
350+}
351+
352+func (c *Hooks) beforeListResources(ctx context.Context, id any, message *mcp.ListResourcesRequest) {
353+ c.beforeAny(ctx, id, mcp.MethodResourcesList, message)
354+ if c == nil {
355+ return
356+ }
357+ for _, hook := range c.OnBeforeListResources {
358+ hook(ctx, id, message)
359+ }
360+}
361+
362+func (c *Hooks) afterListResources(ctx context.Context, id any, message *mcp.ListResourcesRequest, result *mcp.ListResourcesResult) {
363+ c.onSuccess(ctx, id, mcp.MethodResourcesList, message, result)
364+ if c == nil {
365+ return
366+ }
367+ for _, hook := range c.OnAfterListResources {
368+ hook(ctx, id, message, result)
369+ }
370+}
371+func (c *Hooks) AddBeforeListResourceTemplates(hook OnBeforeListResourceTemplatesFunc) {
372+ c.OnBeforeListResourceTemplates = append(c.OnBeforeListResourceTemplates, hook)
373+}
374+
375+func (c *Hooks) AddAfterListResourceTemplates(hook OnAfterListResourceTemplatesFunc) {
376+ c.OnAfterListResourceTemplates = append(c.OnAfterListResourceTemplates, hook)
377+}
378+
379+func (c *Hooks) beforeListResourceTemplates(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest) {
380+ c.beforeAny(ctx, id, mcp.MethodResourcesTemplatesList, message)
381+ if c == nil {
382+ return
383+ }
384+ for _, hook := range c.OnBeforeListResourceTemplates {
385+ hook(ctx, id, message)
386+ }
387+}
388+
389+func (c *Hooks) afterListResourceTemplates(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest, result *mcp.ListResourceTemplatesResult) {
390+ c.onSuccess(ctx, id, mcp.MethodResourcesTemplatesList, message, result)
391+ if c == nil {
392+ return
393+ }
394+ for _, hook := range c.OnAfterListResourceTemplates {
395+ hook(ctx, id, message, result)
396+ }
397+}
398+func (c *Hooks) AddBeforeReadResource(hook OnBeforeReadResourceFunc) {
399+ c.OnBeforeReadResource = append(c.OnBeforeReadResource, hook)
400+}
401+
402+func (c *Hooks) AddAfterReadResource(hook OnAfterReadResourceFunc) {
403+ c.OnAfterReadResource = append(c.OnAfterReadResource, hook)
404+}
405+
406+func (c *Hooks) beforeReadResource(ctx context.Context, id any, message *mcp.ReadResourceRequest) {
407+ c.beforeAny(ctx, id, mcp.MethodResourcesRead, message)
408+ if c == nil {
409+ return
410+ }
411+ for _, hook := range c.OnBeforeReadResource {
412+ hook(ctx, id, message)
413+ }
414+}
415+
416+func (c *Hooks) afterReadResource(ctx context.Context, id any, message *mcp.ReadResourceRequest, result *mcp.ReadResourceResult) {
417+ c.onSuccess(ctx, id, mcp.MethodResourcesRead, message, result)
418+ if c == nil {
419+ return
420+ }
421+ for _, hook := range c.OnAfterReadResource {
422+ hook(ctx, id, message, result)
423+ }
424+}
425+func (c *Hooks) AddBeforeListPrompts(hook OnBeforeListPromptsFunc) {
426+ c.OnBeforeListPrompts = append(c.OnBeforeListPrompts, hook)
427+}
428+
429+func (c *Hooks) AddAfterListPrompts(hook OnAfterListPromptsFunc) {
430+ c.OnAfterListPrompts = append(c.OnAfterListPrompts, hook)
431+}
432+
433+func (c *Hooks) beforeListPrompts(ctx context.Context, id any, message *mcp.ListPromptsRequest) {
434+ c.beforeAny(ctx, id, mcp.MethodPromptsList, message)
435+ if c == nil {
436+ return
437+ }
438+ for _, hook := range c.OnBeforeListPrompts {
439+ hook(ctx, id, message)
440+ }
441+}
442+
443+func (c *Hooks) afterListPrompts(ctx context.Context, id any, message *mcp.ListPromptsRequest, result *mcp.ListPromptsResult) {
444+ c.onSuccess(ctx, id, mcp.MethodPromptsList, message, result)
445+ if c == nil {
446+ return
447+ }
448+ for _, hook := range c.OnAfterListPrompts {
449+ hook(ctx, id, message, result)
450+ }
451+}
452+func (c *Hooks) AddBeforeGetPrompt(hook OnBeforeGetPromptFunc) {
453+ c.OnBeforeGetPrompt = append(c.OnBeforeGetPrompt, hook)
454+}
455+
456+func (c *Hooks) AddAfterGetPrompt(hook OnAfterGetPromptFunc) {
457+ c.OnAfterGetPrompt = append(c.OnAfterGetPrompt, hook)
458+}
459+
460+func (c *Hooks) beforeGetPrompt(ctx context.Context, id any, message *mcp.GetPromptRequest) {
461+ c.beforeAny(ctx, id, mcp.MethodPromptsGet, message)
462+ if c == nil {
463+ return
464+ }
465+ for _, hook := range c.OnBeforeGetPrompt {
466+ hook(ctx, id, message)
467+ }
468+}
469+
470+func (c *Hooks) afterGetPrompt(ctx context.Context, id any, message *mcp.GetPromptRequest, result *mcp.GetPromptResult) {
471+ c.onSuccess(ctx, id, mcp.MethodPromptsGet, message, result)
472+ if c == nil {
473+ return
474+ }
475+ for _, hook := range c.OnAfterGetPrompt {
476+ hook(ctx, id, message, result)
477+ }
478+}
479+func (c *Hooks) AddBeforeListTools(hook OnBeforeListToolsFunc) {
480+ c.OnBeforeListTools = append(c.OnBeforeListTools, hook)
481+}
482+
483+func (c *Hooks) AddAfterListTools(hook OnAfterListToolsFunc) {
484+ c.OnAfterListTools = append(c.OnAfterListTools, hook)
485+}
486+
487+func (c *Hooks) beforeListTools(ctx context.Context, id any, message *mcp.ListToolsRequest) {
488+ c.beforeAny(ctx, id, mcp.MethodToolsList, message)
489+ if c == nil {
490+ return
491+ }
492+ for _, hook := range c.OnBeforeListTools {
493+ hook(ctx, id, message)
494+ }
495+}
496+
497+func (c *Hooks) afterListTools(ctx context.Context, id any, message *mcp.ListToolsRequest, result *mcp.ListToolsResult) {
498+ c.onSuccess(ctx, id, mcp.MethodToolsList, message, result)
499+ if c == nil {
500+ return
501+ }
502+ for _, hook := range c.OnAfterListTools {
503+ hook(ctx, id, message, result)
504+ }
505+}
506+func (c *Hooks) AddBeforeCallTool(hook OnBeforeCallToolFunc) {
507+ c.OnBeforeCallTool = append(c.OnBeforeCallTool, hook)
508+}
509+
510+func (c *Hooks) AddAfterCallTool(hook OnAfterCallToolFunc) {
511+ c.OnAfterCallTool = append(c.OnAfterCallTool, hook)
512+}
513+
514+func (c *Hooks) beforeCallTool(ctx context.Context, id any, message *mcp.CallToolRequest) {
515+ c.beforeAny(ctx, id, mcp.MethodToolsCall, message)
516+ if c == nil {
517+ return
518+ }
519+ for _, hook := range c.OnBeforeCallTool {
520+ hook(ctx, id, message)
521+ }
522+}
523+
524+func (c *Hooks) afterCallTool(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult) {
525+ c.onSuccess(ctx, id, mcp.MethodToolsCall, message, result)
526+ if c == nil {
527+ return
528+ }
529+ for _, hook := range c.OnAfterCallTool {
530+ hook(ctx, id, message, result)
531+ }
532+}
vendor/github.com/mark3labs/mcp-go/server/http_transport_options.gonew file+11
@@ -0,0 +1,11 @@
1+package server
2+
3+import (
4+ "context"
5+ "net/http"
6+)
7+
8+// HTTPContextFunc is a function that takes an existing context and the current
9+// request and returns a potentially modified context based on the request
10+// content. This can be used to inject context values from headers, for example.
11+type HTTPContextFunc func(ctx context.Context, r *http.Request) context.Context
vendor/github.com/mark3labs/mcp-go/server/request_handler.gonew file+320
@@ -0,0 +1,320 @@
1+// Code generated by `go generate`. DO NOT EDIT.
2+// source: server/internal/gen/request_handler.go.tmpl
3+package server
4+
5+import (
6+ "context"
7+ "encoding/json"
8+ "fmt"
9+
10+ "github.com/mark3labs/mcp-go/mcp"
11+)
12+
13+// HandleMessage processes an incoming JSON-RPC message and returns an appropriate response
14+func (s *MCPServer) HandleMessage(
15+ ctx context.Context,
16+ message json.RawMessage,
17+) mcp.JSONRPCMessage {
18+ // Add server to context
19+ ctx = context.WithValue(ctx, serverKey{}, s)
20+ var err *requestError
21+
22+ var baseMessage struct {
23+ JSONRPC string `json:"jsonrpc"`
24+ Method mcp.MCPMethod `json:"method"`
25+ ID any `json:"id,omitempty"`
26+ Result any `json:"result,omitempty"`
27+ }
28+
29+ if err := json.Unmarshal(message, &baseMessage); err != nil {
30+ return createErrorResponse(
31+ nil,
32+ mcp.PARSE_ERROR,
33+ "Failed to parse message",
34+ )
35+ }
36+
37+ // Check for valid JSONRPC version
38+ if baseMessage.JSONRPC != mcp.JSONRPC_VERSION {
39+ return createErrorResponse(
40+ baseMessage.ID,
41+ mcp.INVALID_REQUEST,
42+ "Invalid JSON-RPC version",
43+ )
44+ }
45+
46+ if baseMessage.ID == nil {
47+ var notification mcp.JSONRPCNotification
48+ if err := json.Unmarshal(message, &notification); err != nil {
49+ return createErrorResponse(
50+ nil,
51+ mcp.PARSE_ERROR,
52+ "Failed to parse notification",
53+ )
54+ }
55+ s.handleNotification(ctx, notification)
56+ return nil // Return nil for notifications
57+ }
58+
59+ if baseMessage.Result != nil {
60+ // this is a response to a request sent by the server (e.g. from a ping
61+ // sent due to WithKeepAlive option)
62+ return nil
63+ }
64+
65+ handleErr := s.hooks.onRequestInitialization(ctx, baseMessage.ID, message)
66+ if handleErr != nil {
67+ return createErrorResponse(
68+ baseMessage.ID,
69+ mcp.INVALID_REQUEST,
70+ handleErr.Error(),
71+ )
72+ }
73+
74+ switch baseMessage.Method {
75+ case mcp.MethodInitialize:
76+ var request mcp.InitializeRequest
77+ var result *mcp.InitializeResult
78+ if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
79+ err = &requestError{
80+ id: baseMessage.ID,
81+ code: mcp.INVALID_REQUEST,
82+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
83+ }
84+ } else {
85+ s.hooks.beforeInitialize(ctx, baseMessage.ID, &request)
86+ result, err = s.handleInitialize(ctx, baseMessage.ID, request)
87+ }
88+ if err != nil {
89+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
90+ return err.ToJSONRPCError()
91+ }
92+ s.hooks.afterInitialize(ctx, baseMessage.ID, &request, result)
93+ return createResponse(baseMessage.ID, *result)
94+ case mcp.MethodPing:
95+ var request mcp.PingRequest
96+ var result *mcp.EmptyResult
97+ if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
98+ err = &requestError{
99+ id: baseMessage.ID,
100+ code: mcp.INVALID_REQUEST,
101+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
102+ }
103+ } else {
104+ s.hooks.beforePing(ctx, baseMessage.ID, &request)
105+ result, err = s.handlePing(ctx, baseMessage.ID, request)
106+ }
107+ if err != nil {
108+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
109+ return err.ToJSONRPCError()
110+ }
111+ s.hooks.afterPing(ctx, baseMessage.ID, &request, result)
112+ return createResponse(baseMessage.ID, *result)
113+ case mcp.MethodSetLogLevel:
114+ var request mcp.SetLevelRequest
115+ var result *mcp.EmptyResult
116+ if s.capabilities.logging == nil {
117+ err = &requestError{
118+ id: baseMessage.ID,
119+ code: mcp.METHOD_NOT_FOUND,
120+ err: fmt.Errorf("logging %w", ErrUnsupported),
121+ }
122+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
123+ err = &requestError{
124+ id: baseMessage.ID,
125+ code: mcp.INVALID_REQUEST,
126+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
127+ }
128+ } else {
129+ s.hooks.beforeSetLevel(ctx, baseMessage.ID, &request)
130+ result, err = s.handleSetLevel(ctx, baseMessage.ID, request)
131+ }
132+ if err != nil {
133+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
134+ return err.ToJSONRPCError()
135+ }
136+ s.hooks.afterSetLevel(ctx, baseMessage.ID, &request, result)
137+ return createResponse(baseMessage.ID, *result)
138+ case mcp.MethodResourcesList:
139+ var request mcp.ListResourcesRequest
140+ var result *mcp.ListResourcesResult
141+ if s.capabilities.resources == nil {
142+ err = &requestError{
143+ id: baseMessage.ID,
144+ code: mcp.METHOD_NOT_FOUND,
145+ err: fmt.Errorf("resources %w", ErrUnsupported),
146+ }
147+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
148+ err = &requestError{
149+ id: baseMessage.ID,
150+ code: mcp.INVALID_REQUEST,
151+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
152+ }
153+ } else {
154+ s.hooks.beforeListResources(ctx, baseMessage.ID, &request)
155+ result, err = s.handleListResources(ctx, baseMessage.ID, request)
156+ }
157+ if err != nil {
158+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
159+ return err.ToJSONRPCError()
160+ }
161+ s.hooks.afterListResources(ctx, baseMessage.ID, &request, result)
162+ return createResponse(baseMessage.ID, *result)
163+ case mcp.MethodResourcesTemplatesList:
164+ var request mcp.ListResourceTemplatesRequest
165+ var result *mcp.ListResourceTemplatesResult
166+ if s.capabilities.resources == nil {
167+ err = &requestError{
168+ id: baseMessage.ID,
169+ code: mcp.METHOD_NOT_FOUND,
170+ err: fmt.Errorf("resources %w", ErrUnsupported),
171+ }
172+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
173+ err = &requestError{
174+ id: baseMessage.ID,
175+ code: mcp.INVALID_REQUEST,
176+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
177+ }
178+ } else {
179+ s.hooks.beforeListResourceTemplates(ctx, baseMessage.ID, &request)
180+ result, err = s.handleListResourceTemplates(ctx, baseMessage.ID, request)
181+ }
182+ if err != nil {
183+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
184+ return err.ToJSONRPCError()
185+ }
186+ s.hooks.afterListResourceTemplates(ctx, baseMessage.ID, &request, result)
187+ return createResponse(baseMessage.ID, *result)
188+ case mcp.MethodResourcesRead:
189+ var request mcp.ReadResourceRequest
190+ var result *mcp.ReadResourceResult
191+ if s.capabilities.resources == nil {
192+ err = &requestError{
193+ id: baseMessage.ID,
194+ code: mcp.METHOD_NOT_FOUND,
195+ err: fmt.Errorf("resources %w", ErrUnsupported),
196+ }
197+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
198+ err = &requestError{
199+ id: baseMessage.ID,
200+ code: mcp.INVALID_REQUEST,
201+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
202+ }
203+ } else {
204+ s.hooks.beforeReadResource(ctx, baseMessage.ID, &request)
205+ result, err = s.handleReadResource(ctx, baseMessage.ID, request)
206+ }
207+ if err != nil {
208+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
209+ return err.ToJSONRPCError()
210+ }
211+ s.hooks.afterReadResource(ctx, baseMessage.ID, &request, result)
212+ return createResponse(baseMessage.ID, *result)
213+ case mcp.MethodPromptsList:
214+ var request mcp.ListPromptsRequest
215+ var result *mcp.ListPromptsResult
216+ if s.capabilities.prompts == nil {
217+ err = &requestError{
218+ id: baseMessage.ID,
219+ code: mcp.METHOD_NOT_FOUND,
220+ err: fmt.Errorf("prompts %w", ErrUnsupported),
221+ }
222+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
223+ err = &requestError{
224+ id: baseMessage.ID,
225+ code: mcp.INVALID_REQUEST,
226+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
227+ }
228+ } else {
229+ s.hooks.beforeListPrompts(ctx, baseMessage.ID, &request)
230+ result, err = s.handleListPrompts(ctx, baseMessage.ID, request)
231+ }
232+ if err != nil {
233+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
234+ return err.ToJSONRPCError()
235+ }
236+ s.hooks.afterListPrompts(ctx, baseMessage.ID, &request, result)
237+ return createResponse(baseMessage.ID, *result)
238+ case mcp.MethodPromptsGet:
239+ var request mcp.GetPromptRequest
240+ var result *mcp.GetPromptResult
241+ if s.capabilities.prompts == nil {
242+ err = &requestError{
243+ id: baseMessage.ID,
244+ code: mcp.METHOD_NOT_FOUND,
245+ err: fmt.Errorf("prompts %w", ErrUnsupported),
246+ }
247+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
248+ err = &requestError{
249+ id: baseMessage.ID,
250+ code: mcp.INVALID_REQUEST,
251+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
252+ }
253+ } else {
254+ s.hooks.beforeGetPrompt(ctx, baseMessage.ID, &request)
255+ result, err = s.handleGetPrompt(ctx, baseMessage.ID, request)
256+ }
257+ if err != nil {
258+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
259+ return err.ToJSONRPCError()
260+ }
261+ s.hooks.afterGetPrompt(ctx, baseMessage.ID, &request, result)
262+ return createResponse(baseMessage.ID, *result)
263+ case mcp.MethodToolsList:
264+ var request mcp.ListToolsRequest
265+ var result *mcp.ListToolsResult
266+ if s.capabilities.tools == nil {
267+ err = &requestError{
268+ id: baseMessage.ID,
269+ code: mcp.METHOD_NOT_FOUND,
270+ err: fmt.Errorf("tools %w", ErrUnsupported),
271+ }
272+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
273+ err = &requestError{
274+ id: baseMessage.ID,
275+ code: mcp.INVALID_REQUEST,
276+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
277+ }
278+ } else {
279+ s.hooks.beforeListTools(ctx, baseMessage.ID, &request)
280+ result, err = s.handleListTools(ctx, baseMessage.ID, request)
281+ }
282+ if err != nil {
283+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
284+ return err.ToJSONRPCError()
285+ }
286+ s.hooks.afterListTools(ctx, baseMessage.ID, &request, result)
287+ return createResponse(baseMessage.ID, *result)
288+ case mcp.MethodToolsCall:
289+ var request mcp.CallToolRequest
290+ var result *mcp.CallToolResult
291+ if s.capabilities.tools == nil {
292+ err = &requestError{
293+ id: baseMessage.ID,
294+ code: mcp.METHOD_NOT_FOUND,
295+ err: fmt.Errorf("tools %w", ErrUnsupported),
296+ }
297+ } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil {
298+ err = &requestError{
299+ id: baseMessage.ID,
300+ code: mcp.INVALID_REQUEST,
301+ err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method},
302+ }
303+ } else {
304+ s.hooks.beforeCallTool(ctx, baseMessage.ID, &request)
305+ result, err = s.handleToolCall(ctx, baseMessage.ID, request)
306+ }
307+ if err != nil {
308+ s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err)
309+ return err.ToJSONRPCError()
310+ }
311+ s.hooks.afterCallTool(ctx, baseMessage.ID, &request, result)
312+ return createResponse(baseMessage.ID, *result)
313+ default:
314+ return createErrorResponse(
315+ baseMessage.ID,
316+ mcp.METHOD_NOT_FOUND,
317+ fmt.Sprintf("Method %s not found", baseMessage.Method),
318+ )
319+ }
320+}
vendor/github.com/mark3labs/mcp-go/server/server.gonew file+1079
@@ -0,0 +1,1079 @@
1+// Package server provides MCP (Model Context Protocol) server implementations.
2+package server
3+
4+import (
5+ "context"
6+ "encoding/base64"
7+ "encoding/json"
8+ "fmt"
9+ "slices"
10+ "sort"
11+ "sync"
12+
13+ "github.com/mark3labs/mcp-go/mcp"
14+)
15+
16+// resourceEntry holds both a resource and its handler
17+type resourceEntry struct {
18+ resource mcp.Resource
19+ handler ResourceHandlerFunc
20+}
21+
22+// resourceTemplateEntry holds both a template and its handler
23+type resourceTemplateEntry struct {
24+ template mcp.ResourceTemplate
25+ handler ResourceTemplateHandlerFunc
26+}
27+
28+// ServerOption is a function that configures an MCPServer.
29+type ServerOption func(*MCPServer)
30+
31+// ResourceHandlerFunc is a function that returns resource contents.
32+type ResourceHandlerFunc func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error)
33+
34+// ResourceTemplateHandlerFunc is a function that returns a resource template.
35+type ResourceTemplateHandlerFunc func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error)
36+
37+// PromptHandlerFunc handles prompt requests with given arguments.
38+type PromptHandlerFunc func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error)
39+
40+// ToolHandlerFunc handles tool calls with given arguments.
41+type ToolHandlerFunc func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)
42+
43+// ToolHandlerMiddleware is a middleware function that wraps a ToolHandlerFunc.
44+type ToolHandlerMiddleware func(ToolHandlerFunc) ToolHandlerFunc
45+
46+// ToolFilterFunc is a function that filters tools based on context, typically using session information.
47+type ToolFilterFunc func(ctx context.Context, tools []mcp.Tool) []mcp.Tool
48+
49+// ServerTool combines a Tool with its ToolHandlerFunc.
50+type ServerTool struct {
51+ Tool mcp.Tool
52+ Handler ToolHandlerFunc
53+}
54+
55+// ServerPrompt combines a Prompt with its handler function.
56+type ServerPrompt struct {
57+ Prompt mcp.Prompt
58+ Handler PromptHandlerFunc
59+}
60+
61+// ServerResource combines a Resource with its handler function.
62+type ServerResource struct {
63+ Resource mcp.Resource
64+ Handler ResourceHandlerFunc
65+}
66+
67+// serverKey is the context key for storing the server instance
68+type serverKey struct{}
69+
70+// ServerFromContext retrieves the MCPServer instance from a context
71+func ServerFromContext(ctx context.Context) *MCPServer {
72+ if srv, ok := ctx.Value(serverKey{}).(*MCPServer); ok {
73+ return srv
74+ }
75+ return nil
76+}
77+
78+// UnparsableMessageError is attached to the RequestError when json.Unmarshal
79+// fails on the request.
80+type UnparsableMessageError struct {
81+ message json.RawMessage
82+ method mcp.MCPMethod
83+ err error
84+}
85+
86+func (e *UnparsableMessageError) Error() string {
87+ return fmt.Sprintf("unparsable %s request: %s", e.method, e.err)
88+}
89+
90+func (e *UnparsableMessageError) Unwrap() error {
91+ return e.err
92+}
93+
94+func (e *UnparsableMessageError) GetMessage() json.RawMessage {
95+ return e.message
96+}
97+
98+func (e *UnparsableMessageError) GetMethod() mcp.MCPMethod {
99+ return e.method
100+}
101+
102+// RequestError is an error that can be converted to a JSON-RPC error.
103+// Implements Unwrap() to allow inspecting the error chain.
104+type requestError struct {
105+ id any
106+ code int
107+ err error
108+}
109+
110+func (e *requestError) Error() string {
111+ return fmt.Sprintf("request error: %s", e.err)
112+}
113+
114+func (e *requestError) ToJSONRPCError() mcp.JSONRPCError {
115+ return mcp.JSONRPCError{
116+ JSONRPC: mcp.JSONRPC_VERSION,
117+ ID: mcp.NewRequestId(e.id),
118+ Error: struct {
119+ Code int `json:"code"`
120+ Message string `json:"message"`
121+ Data any `json:"data,omitempty"`
122+ }{
123+ Code: e.code,
124+ Message: e.err.Error(),
125+ },
126+ }
127+}
128+
129+func (e *requestError) Unwrap() error {
130+ return e.err
131+}
132+
133+// NotificationHandlerFunc handles incoming notifications.
134+type NotificationHandlerFunc func(ctx context.Context, notification mcp.JSONRPCNotification)
135+
136+// MCPServer implements a Model Context Protocol server that can handle various types of requests
137+// including resources, prompts, and tools.
138+type MCPServer struct {
139+ // Separate mutexes for different resource types
140+ resourcesMu sync.RWMutex
141+ promptsMu sync.RWMutex
142+ toolsMu sync.RWMutex
143+ middlewareMu sync.RWMutex
144+ notificationHandlersMu sync.RWMutex
145+ capabilitiesMu sync.RWMutex
146+ toolFiltersMu sync.RWMutex
147+
148+ name string
149+ version string
150+ instructions string
151+ resources map[string]resourceEntry
152+ resourceTemplates map[string]resourceTemplateEntry
153+ prompts map[string]mcp.Prompt
154+ promptHandlers map[string]PromptHandlerFunc
155+ tools map[string]ServerTool
156+ toolHandlerMiddlewares []ToolHandlerMiddleware
157+ toolFilters []ToolFilterFunc
158+ notificationHandlers map[string]NotificationHandlerFunc
159+ capabilities serverCapabilities
160+ paginationLimit *int
161+ sessions sync.Map
162+ hooks *Hooks
163+}
164+
165+// WithPaginationLimit sets the pagination limit for the server.
166+func WithPaginationLimit(limit int) ServerOption {
167+ return func(s *MCPServer) {
168+ s.paginationLimit = &limit
169+ }
170+}
171+
172+// serverCapabilities defines the supported features of the MCP server
173+type serverCapabilities struct {
174+ tools *toolCapabilities
175+ resources *resourceCapabilities
176+ prompts *promptCapabilities
177+ logging *bool
178+}
179+
180+// resourceCapabilities defines the supported resource-related features
181+type resourceCapabilities struct {
182+ subscribe bool
183+ listChanged bool
184+}
185+
186+// promptCapabilities defines the supported prompt-related features
187+type promptCapabilities struct {
188+ listChanged bool
189+}
190+
191+// toolCapabilities defines the supported tool-related features
192+type toolCapabilities struct {
193+ listChanged bool
194+}
195+
196+// WithResourceCapabilities configures resource-related server capabilities
197+func WithResourceCapabilities(subscribe, listChanged bool) ServerOption {
198+ return func(s *MCPServer) {
199+ // Always create a non-nil capability object
200+ s.capabilities.resources = &resourceCapabilities{
201+ subscribe: subscribe,
202+ listChanged: listChanged,
203+ }
204+ }
205+}
206+
207+// WithToolHandlerMiddleware allows adding a middleware for the
208+// tool handler call chain.
209+func WithToolHandlerMiddleware(
210+ toolHandlerMiddleware ToolHandlerMiddleware,
211+) ServerOption {
212+ return func(s *MCPServer) {
213+ s.middlewareMu.Lock()
214+ s.toolHandlerMiddlewares = append(s.toolHandlerMiddlewares, toolHandlerMiddleware)
215+ s.middlewareMu.Unlock()
216+ }
217+}
218+
219+// WithToolFilter adds a filter function that will be applied to tools before they are returned in list_tools
220+func WithToolFilter(
221+ toolFilter ToolFilterFunc,
222+) ServerOption {
223+ return func(s *MCPServer) {
224+ s.toolFiltersMu.Lock()
225+ s.toolFilters = append(s.toolFilters, toolFilter)
226+ s.toolFiltersMu.Unlock()
227+ }
228+}
229+
230+// WithRecovery adds a middleware that recovers from panics in tool handlers.
231+func WithRecovery() ServerOption {
232+ return WithToolHandlerMiddleware(func(next ToolHandlerFunc) ToolHandlerFunc {
233+ return func(ctx context.Context, request mcp.CallToolRequest) (result *mcp.CallToolResult, err error) {
234+ defer func() {
235+ if r := recover(); r != nil {
236+ err = fmt.Errorf(
237+ "panic recovered in %s tool handler: %v",
238+ request.Params.Name,
239+ r,
240+ )
241+ }
242+ }()
243+ return next(ctx, request)
244+ }
245+ })
246+}
247+
248+// WithHooks allows adding hooks that will be called before or after
249+// either [all] requests or before / after specific request methods, or else
250+// prior to returning an error to the client.
251+func WithHooks(hooks *Hooks) ServerOption {
252+ return func(s *MCPServer) {
253+ s.hooks = hooks
254+ }
255+}
256+
257+// WithPromptCapabilities configures prompt-related server capabilities
258+func WithPromptCapabilities(listChanged bool) ServerOption {
259+ return func(s *MCPServer) {
260+ // Always create a non-nil capability object
261+ s.capabilities.prompts = &promptCapabilities{
262+ listChanged: listChanged,
263+ }
264+ }
265+}
266+
267+// WithToolCapabilities configures tool-related server capabilities
268+func WithToolCapabilities(listChanged bool) ServerOption {
269+ return func(s *MCPServer) {
270+ // Always create a non-nil capability object
271+ s.capabilities.tools = &toolCapabilities{
272+ listChanged: listChanged,
273+ }
274+ }
275+}
276+
277+// WithLogging enables logging capabilities for the server
278+func WithLogging() ServerOption {
279+ return func(s *MCPServer) {
280+ s.capabilities.logging = mcp.ToBoolPtr(true)
281+ }
282+}
283+
284+// WithInstructions sets the server instructions for the client returned in the initialize response
285+func WithInstructions(instructions string) ServerOption {
286+ return func(s *MCPServer) {
287+ s.instructions = instructions
288+ }
289+}
290+
291+// NewMCPServer creates a new MCP server instance with the given name, version and options
292+func NewMCPServer(
293+ name, version string,
294+ opts ...ServerOption,
295+) *MCPServer {
296+ s := &MCPServer{
297+ resources: make(map[string]resourceEntry),
298+ resourceTemplates: make(map[string]resourceTemplateEntry),
299+ prompts: make(map[string]mcp.Prompt),
300+ promptHandlers: make(map[string]PromptHandlerFunc),
301+ tools: make(map[string]ServerTool),
302+ name: name,
303+ version: version,
304+ notificationHandlers: make(map[string]NotificationHandlerFunc),
305+ capabilities: serverCapabilities{
306+ tools: nil,
307+ resources: nil,
308+ prompts: nil,
309+ logging: nil,
310+ },
311+ }
312+
313+ for _, opt := range opts {
314+ opt(s)
315+ }
316+
317+ return s
318+}
319+
320+// AddResources registers multiple resources at once
321+func (s *MCPServer) AddResources(resources ...ServerResource) {
322+ s.implicitlyRegisterResourceCapabilities()
323+
324+ s.resourcesMu.Lock()
325+ for _, entry := range resources {
326+ s.resources[entry.Resource.URI] = resourceEntry{
327+ resource: entry.Resource,
328+ handler: entry.Handler,
329+ }
330+ }
331+ s.resourcesMu.Unlock()
332+
333+ // When the list of available resources changes, servers that declared the listChanged capability SHOULD send a notification
334+ if s.capabilities.resources.listChanged {
335+ // Send notification to all initialized sessions
336+ s.SendNotificationToAllClients(mcp.MethodNotificationResourcesListChanged, nil)
337+ }
338+}
339+
340+// AddResource registers a new resource and its handler
341+func (s *MCPServer) AddResource(
342+ resource mcp.Resource,
343+ handler ResourceHandlerFunc,
344+) {
345+ s.AddResources(ServerResource{Resource: resource, Handler: handler})
346+}
347+
348+// RemoveResource removes a resource from the server
349+func (s *MCPServer) RemoveResource(uri string) {
350+ s.resourcesMu.Lock()
351+ _, exists := s.resources[uri]
352+ if exists {
353+ delete(s.resources, uri)
354+ }
355+ s.resourcesMu.Unlock()
356+
357+ // Send notification to all initialized sessions if listChanged capability is enabled and we actually remove a resource
358+ if exists && s.capabilities.resources != nil && s.capabilities.resources.listChanged {
359+ s.SendNotificationToAllClients(mcp.MethodNotificationResourcesListChanged, nil)
360+ }
361+}
362+
363+// AddResourceTemplate registers a new resource template and its handler
364+func (s *MCPServer) AddResourceTemplate(
365+ template mcp.ResourceTemplate,
366+ handler ResourceTemplateHandlerFunc,
367+) {
368+ s.implicitlyRegisterResourceCapabilities()
369+
370+ s.resourcesMu.Lock()
371+ s.resourceTemplates[template.URITemplate.Raw()] = resourceTemplateEntry{
372+ template: template,
373+ handler: handler,
374+ }
375+ s.resourcesMu.Unlock()
376+
377+ // When the list of available resources changes, servers that declared the listChanged capability SHOULD send a notification
378+ if s.capabilities.resources.listChanged {
379+ // Send notification to all initialized sessions
380+ s.SendNotificationToAllClients(mcp.MethodNotificationResourcesListChanged, nil)
381+ }
382+}
383+
384+// AddPrompts registers multiple prompts at once
385+func (s *MCPServer) AddPrompts(prompts ...ServerPrompt) {
386+ s.implicitlyRegisterPromptCapabilities()
387+
388+ s.promptsMu.Lock()
389+ for _, entry := range prompts {
390+ s.prompts[entry.Prompt.Name] = entry.Prompt
391+ s.promptHandlers[entry.Prompt.Name] = entry.Handler
392+ }
393+ s.promptsMu.Unlock()
394+
395+ // When the list of available prompts changes, servers that declared the listChanged capability SHOULD send a notification.
396+ if s.capabilities.prompts.listChanged {
397+ // Send notification to all initialized sessions
398+ s.SendNotificationToAllClients(mcp.MethodNotificationPromptsListChanged, nil)
399+ }
400+}
401+
402+// AddPrompt registers a new prompt handler with the given name
403+func (s *MCPServer) AddPrompt(prompt mcp.Prompt, handler PromptHandlerFunc) {
404+ s.AddPrompts(ServerPrompt{Prompt: prompt, Handler: handler})
405+}
406+
407+// DeletePrompts removes prompts from the server
408+func (s *MCPServer) DeletePrompts(names ...string) {
409+ s.promptsMu.Lock()
410+ var exists bool
411+ for _, name := range names {
412+ if _, ok := s.prompts[name]; ok {
413+ delete(s.prompts, name)
414+ delete(s.promptHandlers, name)
415+ exists = true
416+ }
417+ }
418+ s.promptsMu.Unlock()
419+
420+ // Send notification to all initialized sessions if listChanged capability is enabled, and we actually remove a prompt
421+ if exists && s.capabilities.prompts != nil && s.capabilities.prompts.listChanged {
422+ // Send notification to all initialized sessions
423+ s.SendNotificationToAllClients(mcp.MethodNotificationPromptsListChanged, nil)
424+ }
425+}
426+
427+// AddTool registers a new tool and its handler
428+func (s *MCPServer) AddTool(tool mcp.Tool, handler ToolHandlerFunc) {
429+ s.AddTools(ServerTool{Tool: tool, Handler: handler})
430+}
431+
432+// Register tool capabilities due to a tool being added. Default to
433+// listChanged: true, but don't change the value if we've already explicitly
434+// registered tools.listChanged false.
435+func (s *MCPServer) implicitlyRegisterToolCapabilities() {
436+ s.implicitlyRegisterCapabilities(
437+ func() bool { return s.capabilities.tools != nil },
438+ func() { s.capabilities.tools = &toolCapabilities{listChanged: true} },
439+ )
440+}
441+
442+func (s *MCPServer) implicitlyRegisterResourceCapabilities() {
443+ s.implicitlyRegisterCapabilities(
444+ func() bool { return s.capabilities.resources != nil },
445+ func() { s.capabilities.resources = &resourceCapabilities{} },
446+ )
447+}
448+
449+func (s *MCPServer) implicitlyRegisterPromptCapabilities() {
450+ s.implicitlyRegisterCapabilities(
451+ func() bool { return s.capabilities.prompts != nil },
452+ func() { s.capabilities.prompts = &promptCapabilities{} },
453+ )
454+}
455+
456+func (s *MCPServer) implicitlyRegisterCapabilities(check func() bool, register func()) {
457+ s.capabilitiesMu.RLock()
458+ if check() {
459+ s.capabilitiesMu.RUnlock()
460+ return
461+ }
462+ s.capabilitiesMu.RUnlock()
463+
464+ s.capabilitiesMu.Lock()
465+ if !check() {
466+ register()
467+ }
468+ s.capabilitiesMu.Unlock()
469+}
470+
471+// AddTools registers multiple tools at once
472+func (s *MCPServer) AddTools(tools ...ServerTool) {
473+ s.implicitlyRegisterToolCapabilities()
474+
475+ s.toolsMu.Lock()
476+ for _, entry := range tools {
477+ s.tools[entry.Tool.Name] = entry
478+ }
479+ s.toolsMu.Unlock()
480+
481+ // When the list of available tools changes, servers that declared the listChanged capability SHOULD send a notification.
482+ if s.capabilities.tools.listChanged {
483+ // Send notification to all initialized sessions
484+ s.SendNotificationToAllClients(mcp.MethodNotificationToolsListChanged, nil)
485+ }
486+}
487+
488+// SetTools replaces all existing tools with the provided list
489+func (s *MCPServer) SetTools(tools ...ServerTool) {
490+ s.toolsMu.Lock()
491+ s.tools = make(map[string]ServerTool, len(tools))
492+ s.toolsMu.Unlock()
493+ s.AddTools(tools...)
494+}
495+
496+// DeleteTools removes tools from the server
497+func (s *MCPServer) DeleteTools(names ...string) {
498+ s.toolsMu.Lock()
499+ var exists bool
500+ for _, name := range names {
501+ if _, ok := s.tools[name]; ok {
502+ delete(s.tools, name)
503+ exists = true
504+ }
505+ }
506+ s.toolsMu.Unlock()
507+
508+ // When the list of available tools changes, servers that declared the listChanged capability SHOULD send a notification.
509+ if exists && s.capabilities.tools != nil && s.capabilities.tools.listChanged {
510+ // Send notification to all initialized sessions
511+ s.SendNotificationToAllClients(mcp.MethodNotificationToolsListChanged, nil)
512+ }
513+}
514+
515+// AddNotificationHandler registers a new handler for incoming notifications
516+func (s *MCPServer) AddNotificationHandler(
517+ method string,
518+ handler NotificationHandlerFunc,
519+) {
520+ s.notificationHandlersMu.Lock()
521+ defer s.notificationHandlersMu.Unlock()
522+ s.notificationHandlers[method] = handler
523+}
524+
525+func (s *MCPServer) handleInitialize(
526+ ctx context.Context,
527+ _ any,
528+ request mcp.InitializeRequest,
529+) (*mcp.InitializeResult, *requestError) {
530+ capabilities := mcp.ServerCapabilities{}
531+
532+ // Only add resource capabilities if they're configured
533+ if s.capabilities.resources != nil {
534+ capabilities.Resources = &struct {
535+ Subscribe bool `json:"subscribe,omitempty"`
536+ ListChanged bool `json:"listChanged,omitempty"`
537+ }{
538+ Subscribe: s.capabilities.resources.subscribe,
539+ ListChanged: s.capabilities.resources.listChanged,
540+ }
541+ }
542+
543+ // Only add prompt capabilities if they're configured
544+ if s.capabilities.prompts != nil {
545+ capabilities.Prompts = &struct {
546+ ListChanged bool `json:"listChanged,omitempty"`
547+ }{
548+ ListChanged: s.capabilities.prompts.listChanged,
549+ }
550+ }
551+
552+ // Only add tool capabilities if they're configured
553+ if s.capabilities.tools != nil {
554+ capabilities.Tools = &struct {
555+ ListChanged bool `json:"listChanged,omitempty"`
556+ }{
557+ ListChanged: s.capabilities.tools.listChanged,
558+ }
559+ }
560+
561+ if s.capabilities.logging != nil && *s.capabilities.logging {
562+ capabilities.Logging = &struct{}{}
563+ }
564+
565+ result := mcp.InitializeResult{
566+ ProtocolVersion: s.protocolVersion(request.Params.ProtocolVersion),
567+ ServerInfo: mcp.Implementation{
568+ Name: s.name,
569+ Version: s.version,
570+ },
571+ Capabilities: capabilities,
572+ Instructions: s.instructions,
573+ }
574+
575+ if session := ClientSessionFromContext(ctx); session != nil {
576+ session.Initialize()
577+
578+ // Store client info if the session supports it
579+ if sessionWithClientInfo, ok := session.(SessionWithClientInfo); ok {
580+ sessionWithClientInfo.SetClientInfo(request.Params.ClientInfo)
581+ }
582+ }
583+ return &result, nil
584+}
585+
586+func (s *MCPServer) protocolVersion(clientVersion string) string {
587+ if slices.Contains(mcp.ValidProtocolVersions, clientVersion) {
588+ return clientVersion
589+ }
590+
591+ return mcp.LATEST_PROTOCOL_VERSION
592+}
593+
594+func (s *MCPServer) handlePing(
595+ _ context.Context,
596+ _ any,
597+ _ mcp.PingRequest,
598+) (*mcp.EmptyResult, *requestError) {
599+ return &mcp.EmptyResult{}, nil
600+}
601+
602+func (s *MCPServer) handleSetLevel(
603+ ctx context.Context,
604+ id any,
605+ request mcp.SetLevelRequest,
606+) (*mcp.EmptyResult, *requestError) {
607+ clientSession := ClientSessionFromContext(ctx)
608+ if clientSession == nil || !clientSession.Initialized() {
609+ return nil, &requestError{
610+ id: id,
611+ code: mcp.INTERNAL_ERROR,
612+ err: ErrSessionNotInitialized,
613+ }
614+ }
615+
616+ sessionLogging, ok := clientSession.(SessionWithLogging)
617+ if !ok {
618+ return nil, &requestError{
619+ id: id,
620+ code: mcp.INTERNAL_ERROR,
621+ err: ErrSessionDoesNotSupportLogging,
622+ }
623+ }
624+
625+ level := request.Params.Level
626+ // Validate logging level
627+ switch level {
628+ case mcp.LoggingLevelDebug, mcp.LoggingLevelInfo, mcp.LoggingLevelNotice,
629+ mcp.LoggingLevelWarning, mcp.LoggingLevelError, mcp.LoggingLevelCritical,
630+ mcp.LoggingLevelAlert, mcp.LoggingLevelEmergency:
631+ // Valid level
632+ default:
633+ return nil, &requestError{
634+ id: id,
635+ code: mcp.INVALID_PARAMS,
636+ err: fmt.Errorf("invalid logging level '%s'", level),
637+ }
638+ }
639+
640+ sessionLogging.SetLogLevel(level)
641+
642+ return &mcp.EmptyResult{}, nil
643+}
644+
645+func listByPagination[T mcp.Named](
646+ _ context.Context,
647+ s *MCPServer,
648+ cursor mcp.Cursor,
649+ allElements []T,
650+) ([]T, mcp.Cursor, error) {
651+ startPos := 0
652+ if cursor != "" {
653+ c, err := base64.StdEncoding.DecodeString(string(cursor))
654+ if err != nil {
655+ return nil, "", err
656+ }
657+ cString := string(c)
658+ startPos = sort.Search(len(allElements), func(i int) bool {
659+ return allElements[i].GetName() > cString
660+ })
661+ }
662+ endPos := len(allElements)
663+ if s.paginationLimit != nil {
664+ if len(allElements) > startPos+*s.paginationLimit {
665+ endPos = startPos + *s.paginationLimit
666+ }
667+ }
668+ elementsToReturn := allElements[startPos:endPos]
669+ // set the next cursor
670+ nextCursor := func() mcp.Cursor {
671+ if s.paginationLimit != nil && len(elementsToReturn) >= *s.paginationLimit {
672+ nc := elementsToReturn[len(elementsToReturn)-1].GetName()
673+ toString := base64.StdEncoding.EncodeToString([]byte(nc))
674+ return mcp.Cursor(toString)
675+ }
676+ return ""
677+ }()
678+ return elementsToReturn, nextCursor, nil
679+}
680+
681+func (s *MCPServer) handleListResources(
682+ ctx context.Context,
683+ id any,
684+ request mcp.ListResourcesRequest,
685+) (*mcp.ListResourcesResult, *requestError) {
686+ s.resourcesMu.RLock()
687+ resources := make([]mcp.Resource, 0, len(s.resources))
688+ for _, entry := range s.resources {
689+ resources = append(resources, entry.resource)
690+ }
691+ s.resourcesMu.RUnlock()
692+
693+ // Sort the resources by name
694+ sort.Slice(resources, func(i, j int) bool {
695+ return resources[i].Name < resources[j].Name
696+ })
697+ resourcesToReturn, nextCursor, err := listByPagination(
698+ ctx,
699+ s,
700+ request.Params.Cursor,
701+ resources,
702+ )
703+ if err != nil {
704+ return nil, &requestError{
705+ id: id,
706+ code: mcp.INVALID_PARAMS,
707+ err: err,
708+ }
709+ }
710+ result := mcp.ListResourcesResult{
711+ Resources: resourcesToReturn,
712+ PaginatedResult: mcp.PaginatedResult{
713+ NextCursor: nextCursor,
714+ },
715+ }
716+ return &result, nil
717+}
718+
719+func (s *MCPServer) handleListResourceTemplates(
720+ ctx context.Context,
721+ id any,
722+ request mcp.ListResourceTemplatesRequest,
723+) (*mcp.ListResourceTemplatesResult, *requestError) {
724+ s.resourcesMu.RLock()
725+ templates := make([]mcp.ResourceTemplate, 0, len(s.resourceTemplates))
726+ for _, entry := range s.resourceTemplates {
727+ templates = append(templates, entry.template)
728+ }
729+ s.resourcesMu.RUnlock()
730+ sort.Slice(templates, func(i, j int) bool {
731+ return templates[i].Name < templates[j].Name
732+ })
733+ templatesToReturn, nextCursor, err := listByPagination(
734+ ctx,
735+ s,
736+ request.Params.Cursor,
737+ templates,
738+ )
739+ if err != nil {
740+ return nil, &requestError{
741+ id: id,
742+ code: mcp.INVALID_PARAMS,
743+ err: err,
744+ }
745+ }
746+ result := mcp.ListResourceTemplatesResult{
747+ ResourceTemplates: templatesToReturn,
748+ PaginatedResult: mcp.PaginatedResult{
749+ NextCursor: nextCursor,
750+ },
751+ }
752+ return &result, nil
753+}
754+
755+func (s *MCPServer) handleReadResource(
756+ ctx context.Context,
757+ id any,
758+ request mcp.ReadResourceRequest,
759+) (*mcp.ReadResourceResult, *requestError) {
760+ s.resourcesMu.RLock()
761+ // First try direct resource handlers
762+ if entry, ok := s.resources[request.Params.URI]; ok {
763+ handler := entry.handler
764+ s.resourcesMu.RUnlock()
765+ contents, err := handler(ctx, request)
766+ if err != nil {
767+ return nil, &requestError{
768+ id: id,
769+ code: mcp.INTERNAL_ERROR,
770+ err: err,
771+ }
772+ }
773+ return &mcp.ReadResourceResult{Contents: contents}, nil
774+ }
775+
776+ // If no direct handler found, try matching against templates
777+ var matchedHandler ResourceTemplateHandlerFunc
778+ var matched bool
779+ for _, entry := range s.resourceTemplates {
780+ template := entry.template
781+ if matchesTemplate(request.Params.URI, template.URITemplate) {
782+ matchedHandler = entry.handler
783+ matched = true
784+ matchedVars := template.URITemplate.Match(request.Params.URI)
785+ // Convert matched variables to a map
786+ request.Params.Arguments = make(map[string]any, len(matchedVars))
787+ for name, value := range matchedVars {
788+ request.Params.Arguments[name] = value.V
789+ }
790+ break
791+ }
792+ }
793+ s.resourcesMu.RUnlock()
794+
795+ if matched {
796+ contents, err := matchedHandler(ctx, request)
797+ if err != nil {
798+ return nil, &requestError{
799+ id: id,
800+ code: mcp.INTERNAL_ERROR,
801+ err: err,
802+ }
803+ }
804+ return &mcp.ReadResourceResult{Contents: contents}, nil
805+ }
806+
807+ return nil, &requestError{
808+ id: id,
809+ code: mcp.RESOURCE_NOT_FOUND,
810+ err: fmt.Errorf(
811+ "handler not found for resource URI '%s': %w",
812+ request.Params.URI,
813+ ErrResourceNotFound,
814+ ),
815+ }
816+}
817+
818+// matchesTemplate checks if a URI matches a URI template pattern
819+func matchesTemplate(uri string, template *mcp.URITemplate) bool {
820+ return template.Regexp().MatchString(uri)
821+}
822+
823+func (s *MCPServer) handleListPrompts(
824+ ctx context.Context,
825+ id any,
826+ request mcp.ListPromptsRequest,
827+) (*mcp.ListPromptsResult, *requestError) {
828+ s.promptsMu.RLock()
829+ prompts := make([]mcp.Prompt, 0, len(s.prompts))
830+ for _, prompt := range s.prompts {
831+ prompts = append(prompts, prompt)
832+ }
833+ s.promptsMu.RUnlock()
834+
835+ // sort prompts by name
836+ sort.Slice(prompts, func(i, j int) bool {
837+ return prompts[i].Name < prompts[j].Name
838+ })
839+ promptsToReturn, nextCursor, err := listByPagination(
840+ ctx,
841+ s,
842+ request.Params.Cursor,
843+ prompts,
844+ )
845+ if err != nil {
846+ return nil, &requestError{
847+ id: id,
848+ code: mcp.INVALID_PARAMS,
849+ err: err,
850+ }
851+ }
852+ result := mcp.ListPromptsResult{
853+ Prompts: promptsToReturn,
854+ PaginatedResult: mcp.PaginatedResult{
855+ NextCursor: nextCursor,
856+ },
857+ }
858+ return &result, nil
859+}
860+
861+func (s *MCPServer) handleGetPrompt(
862+ ctx context.Context,
863+ id any,
864+ request mcp.GetPromptRequest,
865+) (*mcp.GetPromptResult, *requestError) {
866+ s.promptsMu.RLock()
867+ handler, ok := s.promptHandlers[request.Params.Name]
868+ s.promptsMu.RUnlock()
869+
870+ if !ok {
871+ return nil, &requestError{
872+ id: id,
873+ code: mcp.INVALID_PARAMS,
874+ err: fmt.Errorf("prompt '%s' not found: %w", request.Params.Name, ErrPromptNotFound),
875+ }
876+ }
877+
878+ result, err := handler(ctx, request)
879+ if err != nil {
880+ return nil, &requestError{
881+ id: id,
882+ code: mcp.INTERNAL_ERROR,
883+ err: err,
884+ }
885+ }
886+
887+ return result, nil
888+}
889+
890+func (s *MCPServer) handleListTools(
891+ ctx context.Context,
892+ id any,
893+ request mcp.ListToolsRequest,
894+) (*mcp.ListToolsResult, *requestError) {
895+ // Get the base tools from the server
896+ s.toolsMu.RLock()
897+ tools := make([]mcp.Tool, 0, len(s.tools))
898+
899+ // Get all tool names for consistent ordering
900+ toolNames := make([]string, 0, len(s.tools))
901+ for name := range s.tools {
902+ toolNames = append(toolNames, name)
903+ }
904+
905+ // Sort the tool names for consistent ordering
906+ sort.Strings(toolNames)
907+
908+ // Add tools in sorted order
909+ for _, name := range toolNames {
910+ tools = append(tools, s.tools[name].Tool)
911+ }
912+ s.toolsMu.RUnlock()
913+
914+ // Check if there are session-specific tools
915+ session := ClientSessionFromContext(ctx)
916+ if session != nil {
917+ if sessionWithTools, ok := session.(SessionWithTools); ok {
918+ if sessionTools := sessionWithTools.GetSessionTools(); sessionTools != nil {
919+ // Override or add session-specific tools
920+ // We need to create a map first to merge the tools properly
921+ toolMap := make(map[string]mcp.Tool)
922+
923+ // Add global tools first
924+ for _, tool := range tools {
925+ toolMap[tool.Name] = tool
926+ }
927+
928+ // Then override with session-specific tools
929+ for name, serverTool := range sessionTools {
930+ toolMap[name] = serverTool.Tool
931+ }
932+
933+ // Convert back to slice
934+ tools = make([]mcp.Tool, 0, len(toolMap))
935+ for _, tool := range toolMap {
936+ tools = append(tools, tool)
937+ }
938+
939+ // Sort again to maintain consistent ordering
940+ sort.Slice(tools, func(i, j int) bool {
941+ return tools[i].Name < tools[j].Name
942+ })
943+ }
944+ }
945+ }
946+
947+ // Apply tool filters if any are defined
948+ s.toolFiltersMu.RLock()
949+ if len(s.toolFilters) > 0 {
950+ for _, filter := range s.toolFilters {
951+ tools = filter(ctx, tools)
952+ }
953+ }
954+ s.toolFiltersMu.RUnlock()
955+
956+ // Apply pagination
957+ toolsToReturn, nextCursor, err := listByPagination(
958+ ctx,
959+ s,
960+ request.Params.Cursor,
961+ tools,
962+ )
963+ if err != nil {
964+ return nil, &requestError{
965+ id: id,
966+ code: mcp.INVALID_PARAMS,
967+ err: err,
968+ }
969+ }
970+
971+ result := mcp.ListToolsResult{
972+ Tools: toolsToReturn,
973+ PaginatedResult: mcp.PaginatedResult{
974+ NextCursor: nextCursor,
975+ },
976+ }
977+ return &result, nil
978+}
979+
980+func (s *MCPServer) handleToolCall(
981+ ctx context.Context,
982+ id any,
983+ request mcp.CallToolRequest,
984+) (*mcp.CallToolResult, *requestError) {
985+ // First check session-specific tools
986+ var tool ServerTool
987+ var ok bool
988+
989+ session := ClientSessionFromContext(ctx)
990+ if session != nil {
991+ if sessionWithTools, typeAssertOk := session.(SessionWithTools); typeAssertOk {
992+ if sessionTools := sessionWithTools.GetSessionTools(); sessionTools != nil {
993+ var sessionOk bool
994+ tool, sessionOk = sessionTools[request.Params.Name]
995+ if sessionOk {
996+ ok = true
997+ }
998+ }
999+ }
1000+ }
1001+
1002+ // If not found in session tools, check global tools
1003+ if !ok {
1004+ s.toolsMu.RLock()
1005+ tool, ok = s.tools[request.Params.Name]
1006+ s.toolsMu.RUnlock()
1007+ }
1008+
1009+ if !ok {
1010+ return nil, &requestError{
1011+ id: id,
1012+ code: mcp.INVALID_PARAMS,
1013+ err: fmt.Errorf("tool '%s' not found: %w", request.Params.Name, ErrToolNotFound),
1014+ }
1015+ }
1016+
1017+ finalHandler := tool.Handler
1018+
1019+ s.middlewareMu.RLock()
1020+ mw := s.toolHandlerMiddlewares
1021+ s.middlewareMu.RUnlock()
1022+
1023+ // Apply middlewares in reverse order
1024+ for i := len(mw) - 1; i >= 0; i-- {
1025+ finalHandler = mw[i](finalHandler)
1026+ }
1027+
1028+ result, err := finalHandler(ctx, request)
1029+ if err != nil {
1030+ return nil, &requestError{
1031+ id: id,
1032+ code: mcp.INTERNAL_ERROR,
1033+ err: err,
1034+ }
1035+ }
1036+
1037+ return result, nil
1038+}
1039+
1040+func (s *MCPServer) handleNotification(
1041+ ctx context.Context,
1042+ notification mcp.JSONRPCNotification,
1043+) mcp.JSONRPCMessage {
1044+ s.notificationHandlersMu.RLock()
1045+ handler, ok := s.notificationHandlers[notification.Method]
1046+ s.notificationHandlersMu.RUnlock()
1047+
1048+ if ok {
1049+ handler(ctx, notification)
1050+ }
1051+ return nil
1052+}
1053+
1054+func createResponse(id any, result any) mcp.JSONRPCMessage {
1055+ return mcp.JSONRPCResponse{
1056+ JSONRPC: mcp.JSONRPC_VERSION,
1057+ ID: mcp.NewRequestId(id),
1058+ Result: result,
1059+ }
1060+}
1061+
1062+func createErrorResponse(
1063+ id any,
1064+ code int,
1065+ message string,
1066+) mcp.JSONRPCMessage {
1067+ return mcp.JSONRPCError{
1068+ JSONRPC: mcp.JSONRPC_VERSION,
1069+ ID: mcp.NewRequestId(id),
1070+ Error: struct {
1071+ Code int `json:"code"`
1072+ Message string `json:"message"`
1073+ Data any `json:"data,omitempty"`
1074+ }{
1075+ Code: code,
1076+ Message: message,
1077+ },
1078+ }
1079+}
vendor/github.com/mark3labs/mcp-go/server/session.gonew file+380
@@ -0,0 +1,380 @@
1+package server
2+
3+import (
4+ "context"
5+ "fmt"
6+
7+ "github.com/mark3labs/mcp-go/mcp"
8+)
9+
10+// ClientSession represents an active session that can be used by MCPServer to interact with client.
11+type ClientSession interface {
12+ // Initialize marks session as fully initialized and ready for notifications
13+ Initialize()
14+ // Initialized returns if session is ready to accept notifications
15+ Initialized() bool
16+ // NotificationChannel provides a channel suitable for sending notifications to client.
17+ NotificationChannel() chan<- mcp.JSONRPCNotification
18+ // SessionID is a unique identifier used to track user session.
19+ SessionID() string
20+}
21+
22+// SessionWithLogging is an extension of ClientSession that can receive log message notifications and set log level
23+type SessionWithLogging interface {
24+ ClientSession
25+ // SetLogLevel sets the minimum log level
26+ SetLogLevel(level mcp.LoggingLevel)
27+ // GetLogLevel retrieves the minimum log level
28+ GetLogLevel() mcp.LoggingLevel
29+}
30+
31+// SessionWithTools is an extension of ClientSession that can store session-specific tool data
32+type SessionWithTools interface {
33+ ClientSession
34+ // GetSessionTools returns the tools specific to this session, if any
35+ // This method must be thread-safe for concurrent access
36+ GetSessionTools() map[string]ServerTool
37+ // SetSessionTools sets tools specific to this session
38+ // This method must be thread-safe for concurrent access
39+ SetSessionTools(tools map[string]ServerTool)
40+}
41+
42+// SessionWithClientInfo is an extension of ClientSession that can store client info
43+type SessionWithClientInfo interface {
44+ ClientSession
45+ // GetClientInfo returns the client information for this session
46+ GetClientInfo() mcp.Implementation
47+ // SetClientInfo sets the client information for this session
48+ SetClientInfo(clientInfo mcp.Implementation)
49+}
50+
51+// SessionWithStreamableHTTPConfig extends ClientSession to support streamable HTTP transport configurations
52+type SessionWithStreamableHTTPConfig interface {
53+ ClientSession
54+ // UpgradeToSSEWhenReceiveNotification upgrades the client-server communication to SSE stream when the server
55+ // sends notifications to the client
56+ //
57+ // The protocol specification:
58+ // - If the server response contains any JSON-RPC notifications, it MUST either:
59+ // - Return Content-Type: text/event-stream to initiate an SSE stream, OR
60+ // - Return Content-Type: application/json for a single JSON object
61+ // - The client MUST support both response types.
62+ //
63+ // Reference: https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#sending-messages-to-the-server
64+ UpgradeToSSEWhenReceiveNotification()
65+}
66+
67+// clientSessionKey is the context key for storing current client notification channel.
68+type clientSessionKey struct{}
69+
70+// ClientSessionFromContext retrieves current client notification context from context.
71+func ClientSessionFromContext(ctx context.Context) ClientSession {
72+ if session, ok := ctx.Value(clientSessionKey{}).(ClientSession); ok {
73+ return session
74+ }
75+ return nil
76+}
77+
78+// WithContext sets the current client session and returns the provided context
79+func (s *MCPServer) WithContext(
80+ ctx context.Context,
81+ session ClientSession,
82+) context.Context {
83+ return context.WithValue(ctx, clientSessionKey{}, session)
84+}
85+
86+// RegisterSession saves session that should be notified in case if some server attributes changed.
87+func (s *MCPServer) RegisterSession(
88+ ctx context.Context,
89+ session ClientSession,
90+) error {
91+ sessionID := session.SessionID()
92+ if _, exists := s.sessions.LoadOrStore(sessionID, session); exists {
93+ return ErrSessionExists
94+ }
95+ s.hooks.RegisterSession(ctx, session)
96+ return nil
97+}
98+
99+// UnregisterSession removes from storage session that is shut down.
100+func (s *MCPServer) UnregisterSession(
101+ ctx context.Context,
102+ sessionID string,
103+) {
104+ sessionValue, ok := s.sessions.LoadAndDelete(sessionID)
105+ if !ok {
106+ return
107+ }
108+ if session, ok := sessionValue.(ClientSession); ok {
109+ s.hooks.UnregisterSession(ctx, session)
110+ }
111+}
112+
113+// SendNotificationToAllClients sends a notification to all the currently active clients.
114+func (s *MCPServer) SendNotificationToAllClients(
115+ method string,
116+ params map[string]any,
117+) {
118+ notification := mcp.JSONRPCNotification{
119+ JSONRPC: mcp.JSONRPC_VERSION,
120+ Notification: mcp.Notification{
121+ Method: method,
122+ Params: mcp.NotificationParams{
123+ AdditionalFields: params,
124+ },
125+ },
126+ }
127+
128+ s.sessions.Range(func(k, v any) bool {
129+ if session, ok := v.(ClientSession); ok && session.Initialized() {
130+ select {
131+ case session.NotificationChannel() <- notification:
132+ // Successfully sent notification
133+ default:
134+ // Channel is blocked, if there's an error hook, use it
135+ if s.hooks != nil && len(s.hooks.OnError) > 0 {
136+ err := ErrNotificationChannelBlocked
137+ // Copy hooks pointer to local variable to avoid race condition
138+ hooks := s.hooks
139+ go func(sessionID string, hooks *Hooks) {
140+ ctx := context.Background()
141+ // Use the error hook to report the blocked channel
142+ hooks.onError(ctx, nil, "notification", map[string]any{
143+ "method": method,
144+ "sessionID": sessionID,
145+ }, fmt.Errorf("notification channel blocked for session %s: %w", sessionID, err))
146+ }(session.SessionID(), hooks)
147+ }
148+ }
149+ }
150+ return true
151+ })
152+}
153+
154+// SendNotificationToClient sends a notification to the current client
155+func (s *MCPServer) SendNotificationToClient(
156+ ctx context.Context,
157+ method string,
158+ params map[string]any,
159+) error {
160+ session := ClientSessionFromContext(ctx)
161+ if session == nil || !session.Initialized() {
162+ return ErrNotificationNotInitialized
163+ }
164+
165+ // upgrades the client-server communication to SSE stream when the server sends notifications to the client
166+ if sessionWithStreamableHTTPConfig, ok := session.(SessionWithStreamableHTTPConfig); ok {
167+ sessionWithStreamableHTTPConfig.UpgradeToSSEWhenReceiveNotification()
168+ }
169+
170+ notification := mcp.JSONRPCNotification{
171+ JSONRPC: mcp.JSONRPC_VERSION,
172+ Notification: mcp.Notification{
173+ Method: method,
174+ Params: mcp.NotificationParams{
175+ AdditionalFields: params,
176+ },
177+ },
178+ }
179+
180+ select {
181+ case session.NotificationChannel() <- notification:
182+ return nil
183+ default:
184+ // Channel is blocked, if there's an error hook, use it
185+ if s.hooks != nil && len(s.hooks.OnError) > 0 {
186+ err := ErrNotificationChannelBlocked
187+ // Copy hooks pointer to local variable to avoid race condition
188+ hooks := s.hooks
189+ go func(sessionID string, hooks *Hooks) {
190+ // Use the error hook to report the blocked channel
191+ hooks.onError(ctx, nil, "notification", map[string]any{
192+ "method": method,
193+ "sessionID": sessionID,
194+ }, fmt.Errorf("notification channel blocked for session %s: %w", sessionID, err))
195+ }(session.SessionID(), hooks)
196+ }
197+ return ErrNotificationChannelBlocked
198+ }
199+}
200+
201+// SendNotificationToSpecificClient sends a notification to a specific client by session ID
202+func (s *MCPServer) SendNotificationToSpecificClient(
203+ sessionID string,
204+ method string,
205+ params map[string]any,
206+) error {
207+ sessionValue, ok := s.sessions.Load(sessionID)
208+ if !ok {
209+ return ErrSessionNotFound
210+ }
211+
212+ session, ok := sessionValue.(ClientSession)
213+ if !ok || !session.Initialized() {
214+ return ErrSessionNotInitialized
215+ }
216+
217+ // upgrades the client-server communication to SSE stream when the server sends notifications to the client
218+ if sessionWithStreamableHTTPConfig, ok := session.(SessionWithStreamableHTTPConfig); ok {
219+ sessionWithStreamableHTTPConfig.UpgradeToSSEWhenReceiveNotification()
220+ }
221+
222+ notification := mcp.JSONRPCNotification{
223+ JSONRPC: mcp.JSONRPC_VERSION,
224+ Notification: mcp.Notification{
225+ Method: method,
226+ Params: mcp.NotificationParams{
227+ AdditionalFields: params,
228+ },
229+ },
230+ }
231+
232+ select {
233+ case session.NotificationChannel() <- notification:
234+ return nil
235+ default:
236+ // Channel is blocked, if there's an error hook, use it
237+ if s.hooks != nil && len(s.hooks.OnError) > 0 {
238+ err := ErrNotificationChannelBlocked
239+ ctx := context.Background()
240+ // Copy hooks pointer to local variable to avoid race condition
241+ hooks := s.hooks
242+ go func(sID string, hooks *Hooks) {
243+ // Use the error hook to report the blocked channel
244+ hooks.onError(ctx, nil, "notification", map[string]any{
245+ "method": method,
246+ "sessionID": sID,
247+ }, fmt.Errorf("notification channel blocked for session %s: %w", sID, err))
248+ }(sessionID, hooks)
249+ }
250+ return ErrNotificationChannelBlocked
251+ }
252+}
253+
254+// AddSessionTool adds a tool for a specific session
255+func (s *MCPServer) AddSessionTool(sessionID string, tool mcp.Tool, handler ToolHandlerFunc) error {
256+ return s.AddSessionTools(sessionID, ServerTool{Tool: tool, Handler: handler})
257+}
258+
259+// AddSessionTools adds tools for a specific session
260+func (s *MCPServer) AddSessionTools(sessionID string, tools ...ServerTool) error {
261+ sessionValue, ok := s.sessions.Load(sessionID)
262+ if !ok {
263+ return ErrSessionNotFound
264+ }
265+
266+ session, ok := sessionValue.(SessionWithTools)
267+ if !ok {
268+ return ErrSessionDoesNotSupportTools
269+ }
270+
271+ s.implicitlyRegisterToolCapabilities()
272+
273+ // Get existing tools (this should return a thread-safe copy)
274+ sessionTools := session.GetSessionTools()
275+
276+ // Create a new map to avoid concurrent modification issues
277+ newSessionTools := make(map[string]ServerTool, len(sessionTools)+len(tools))
278+
279+ // Copy existing tools
280+ for k, v := range sessionTools {
281+ newSessionTools[k] = v
282+ }
283+
284+ // Add new tools
285+ for _, tool := range tools {
286+ newSessionTools[tool.Tool.Name] = tool
287+ }
288+
289+ // Set the tools (this should be thread-safe)
290+ session.SetSessionTools(newSessionTools)
291+
292+ // It only makes sense to send tool notifications to initialized sessions --
293+ // if we're not initialized yet the client can't possibly have sent their
294+ // initial tools/list message.
295+ //
296+ // For initialized sessions, honor tools.listChanged, which is specifically
297+ // about whether notifications will be sent or not.
298+ // see <https://modelcontextprotocol.io/specification/2025-03-26/server/tools#capabilities>
299+ if session.Initialized() && s.capabilities.tools != nil && s.capabilities.tools.listChanged {
300+ // Send notification only to this session
301+ if err := s.SendNotificationToSpecificClient(sessionID, "notifications/tools/list_changed", nil); err != nil {
302+ // Log the error but don't fail the operation
303+ // The tools were successfully added, but notification failed
304+ if s.hooks != nil && len(s.hooks.OnError) > 0 {
305+ hooks := s.hooks
306+ go func(sID string, hooks *Hooks) {
307+ ctx := context.Background()
308+ hooks.onError(ctx, nil, "notification", map[string]any{
309+ "method": "notifications/tools/list_changed",
310+ "sessionID": sID,
311+ }, fmt.Errorf("failed to send notification after adding tools: %w", err))
312+ }(sessionID, hooks)
313+ }
314+ }
315+ }
316+
317+ return nil
318+}
319+
320+// DeleteSessionTools removes tools from a specific session
321+func (s *MCPServer) DeleteSessionTools(sessionID string, names ...string) error {
322+ sessionValue, ok := s.sessions.Load(sessionID)
323+ if !ok {
324+ return ErrSessionNotFound
325+ }
326+
327+ session, ok := sessionValue.(SessionWithTools)
328+ if !ok {
329+ return ErrSessionDoesNotSupportTools
330+ }
331+
332+ // Get existing tools (this should return a thread-safe copy)
333+ sessionTools := session.GetSessionTools()
334+ if sessionTools == nil {
335+ return nil
336+ }
337+
338+ // Create a new map to avoid concurrent modification issues
339+ newSessionTools := make(map[string]ServerTool, len(sessionTools))
340+
341+ // Copy existing tools except those being deleted
342+ for k, v := range sessionTools {
343+ newSessionTools[k] = v
344+ }
345+
346+ // Remove specified tools
347+ for _, name := range names {
348+ delete(newSessionTools, name)
349+ }
350+
351+ // Set the tools (this should be thread-safe)
352+ session.SetSessionTools(newSessionTools)
353+
354+ // It only makes sense to send tool notifications to initialized sessions --
355+ // if we're not initialized yet the client can't possibly have sent their
356+ // initial tools/list message.
357+ //
358+ // For initialized sessions, honor tools.listChanged, which is specifically
359+ // about whether notifications will be sent or not.
360+ // see <https://modelcontextprotocol.io/specification/2025-03-26/server/tools#capabilities>
361+ if session.Initialized() && s.capabilities.tools != nil && s.capabilities.tools.listChanged {
362+ // Send notification only to this session
363+ if err := s.SendNotificationToSpecificClient(sessionID, "notifications/tools/list_changed", nil); err != nil {
364+ // Log the error but don't fail the operation
365+ // The tools were successfully deleted, but notification failed
366+ if s.hooks != nil && len(s.hooks.OnError) > 0 {
367+ hooks := s.hooks
368+ go func(sID string, hooks *Hooks) {
369+ ctx := context.Background()
370+ hooks.onError(ctx, nil, "notification", map[string]any{
371+ "method": "notifications/tools/list_changed",
372+ "sessionID": sID,
373+ }, fmt.Errorf("failed to send notification after deleting tools: %w", err))
374+ }(sessionID, hooks)
375+ }
376+ }
377+ }
378+
379+ return nil
380+}
vendor/github.com/mark3labs/mcp-go/server/sse.gonew file+736
@@ -0,0 +1,736 @@
1+package server
2+
3+import (
4+ "context"
5+ "encoding/json"
6+ "fmt"
7+ "log"
8+ "net/http"
9+ "net/http/httptest"
10+ "net/url"
11+ "path"
12+ "strings"
13+ "sync"
14+ "sync/atomic"
15+ "time"
16+
17+ "github.com/google/uuid"
18+
19+ "github.com/mark3labs/mcp-go/mcp"
20+)
21+
22+// sseSession represents an active SSE connection.
23+type sseSession struct {
24+ done chan struct{}
25+ eventQueue chan string // Channel for queuing events
26+ sessionID string
27+ requestID atomic.Int64
28+ notificationChannel chan mcp.JSONRPCNotification
29+ initialized atomic.Bool
30+ loggingLevel atomic.Value
31+ tools sync.Map // stores session-specific tools
32+ clientInfo atomic.Value // stores session-specific client info
33+}
34+
35+// SSEContextFunc is a function that takes an existing context and the current
36+// request and returns a potentially modified context based on the request
37+// content. This can be used to inject context values from headers, for example.
38+type SSEContextFunc func(ctx context.Context, r *http.Request) context.Context
39+
40+// DynamicBasePathFunc allows the user to provide a function to generate the
41+// base path for a given request and sessionID. This is useful for cases where
42+// the base path is not known at the time of SSE server creation, such as when
43+// using a reverse proxy or when the base path is dynamically generated. The
44+// function should return the base path (e.g., "/mcp/tenant123").
45+type DynamicBasePathFunc func(r *http.Request, sessionID string) string
46+
47+func (s *sseSession) SessionID() string {
48+ return s.sessionID
49+}
50+
51+func (s *sseSession) NotificationChannel() chan<- mcp.JSONRPCNotification {
52+ return s.notificationChannel
53+}
54+
55+func (s *sseSession) Initialize() {
56+ // set default logging level
57+ s.loggingLevel.Store(mcp.LoggingLevelError)
58+ s.initialized.Store(true)
59+}
60+
61+func (s *sseSession) Initialized() bool {
62+ return s.initialized.Load()
63+}
64+
65+func (s *sseSession) SetLogLevel(level mcp.LoggingLevel) {
66+ s.loggingLevel.Store(level)
67+}
68+
69+func (s *sseSession) GetLogLevel() mcp.LoggingLevel {
70+ level := s.loggingLevel.Load()
71+ if level == nil {
72+ return mcp.LoggingLevelError
73+ }
74+ return level.(mcp.LoggingLevel)
75+}
76+
77+func (s *sseSession) GetSessionTools() map[string]ServerTool {
78+ tools := make(map[string]ServerTool)
79+ s.tools.Range(func(key, value any) bool {
80+ if tool, ok := value.(ServerTool); ok {
81+ tools[key.(string)] = tool
82+ }
83+ return true
84+ })
85+ return tools
86+}
87+
88+func (s *sseSession) SetSessionTools(tools map[string]ServerTool) {
89+ // Clear existing tools
90+ s.tools.Clear()
91+
92+ // Set new tools
93+ for name, tool := range tools {
94+ s.tools.Store(name, tool)
95+ }
96+}
97+
98+func (s *sseSession) GetClientInfo() mcp.Implementation {
99+ if value := s.clientInfo.Load(); value != nil {
100+ if clientInfo, ok := value.(mcp.Implementation); ok {
101+ return clientInfo
102+ }
103+ }
104+ return mcp.Implementation{}
105+}
106+
107+func (s *sseSession) SetClientInfo(clientInfo mcp.Implementation) {
108+ s.clientInfo.Store(clientInfo)
109+}
110+
111+var (
112+ _ ClientSession = (*sseSession)(nil)
113+ _ SessionWithTools = (*sseSession)(nil)
114+ _ SessionWithLogging = (*sseSession)(nil)
115+ _ SessionWithClientInfo = (*sseSession)(nil)
116+)
117+
118+// SSEServer implements a Server-Sent Events (SSE) based MCP server.
119+// It provides real-time communication capabilities over HTTP using the SSE protocol.
120+type SSEServer struct {
121+ server *MCPServer
122+ baseURL string
123+ basePath string
124+ appendQueryToMessageEndpoint bool
125+ useFullURLForMessageEndpoint bool
126+ messageEndpoint string
127+ sseEndpoint string
128+ sessions sync.Map
129+ srv *http.Server
130+ contextFunc SSEContextFunc
131+ dynamicBasePathFunc DynamicBasePathFunc
132+
133+ keepAlive bool
134+ keepAliveInterval time.Duration
135+
136+ mu sync.RWMutex
137+}
138+
139+// SSEOption defines a function type for configuring SSEServer
140+type SSEOption func(*SSEServer)
141+
142+// WithBaseURL sets the base URL for the SSE server
143+func WithBaseURL(baseURL string) SSEOption {
144+ return func(s *SSEServer) {
145+ if baseURL != "" {
146+ u, err := url.Parse(baseURL)
147+ if err != nil {
148+ return
149+ }
150+ if u.Scheme != "http" && u.Scheme != "https" {
151+ return
152+ }
153+ // Check if the host is empty or only contains a port
154+ if u.Host == "" || strings.HasPrefix(u.Host, ":") {
155+ return
156+ }
157+ if len(u.Query()) > 0 {
158+ return
159+ }
160+ }
161+ s.baseURL = strings.TrimSuffix(baseURL, "/")
162+ }
163+}
164+
165+// WithStaticBasePath adds a new option for setting a static base path
166+func WithStaticBasePath(basePath string) SSEOption {
167+ return func(s *SSEServer) {
168+ s.basePath = normalizeURLPath(basePath)
169+ }
170+}
171+
172+// WithBasePath adds a new option for setting a static base path.
173+//
174+// Deprecated: Use WithStaticBasePath instead. This will be removed in a future version.
175+//
176+//go:deprecated
177+func WithBasePath(basePath string) SSEOption {
178+ return WithStaticBasePath(basePath)
179+}
180+
181+// WithDynamicBasePath accepts a function for generating the base path. This is
182+// useful for cases where the base path is not known at the time of SSE server
183+// creation, such as when using a reverse proxy or when the server is mounted
184+// at a dynamic path.
185+func WithDynamicBasePath(fn DynamicBasePathFunc) SSEOption {
186+ return func(s *SSEServer) {
187+ if fn != nil {
188+ s.dynamicBasePathFunc = func(r *http.Request, sid string) string {
189+ bp := fn(r, sid)
190+ return normalizeURLPath(bp)
191+ }
192+ }
193+ }
194+}
195+
196+// WithMessageEndpoint sets the message endpoint path
197+func WithMessageEndpoint(endpoint string) SSEOption {
198+ return func(s *SSEServer) {
199+ s.messageEndpoint = endpoint
200+ }
201+}
202+
203+// WithAppendQueryToMessageEndpoint configures the SSE server to append the original request's
204+// query parameters to the message endpoint URL that is sent to clients during the SSE connection
205+// initialization. This is useful when you need to preserve query parameters from the initial
206+// SSE connection request and carry them over to subsequent message requests, maintaining
207+// context or authentication details across the communication channel.
208+func WithAppendQueryToMessageEndpoint() SSEOption {
209+ return func(s *SSEServer) {
210+ s.appendQueryToMessageEndpoint = true
211+ }
212+}
213+
214+// WithUseFullURLForMessageEndpoint controls whether the SSE server returns a complete URL (including baseURL)
215+// or just the path portion for the message endpoint. Set to false when clients will concatenate
216+// the baseURL themselves to avoid malformed URLs like "http://localhost/mcphttp://localhost/mcp/message".
217+func WithUseFullURLForMessageEndpoint(useFullURLForMessageEndpoint bool) SSEOption {
218+ return func(s *SSEServer) {
219+ s.useFullURLForMessageEndpoint = useFullURLForMessageEndpoint
220+ }
221+}
222+
223+// WithSSEEndpoint sets the SSE endpoint path
224+func WithSSEEndpoint(endpoint string) SSEOption {
225+ return func(s *SSEServer) {
226+ s.sseEndpoint = endpoint
227+ }
228+}
229+
230+// WithHTTPServer sets the HTTP server instance.
231+// NOTE: When providing a custom HTTP server, you must handle routing yourself
232+// If routing is not set up, the server will start but won't handle any MCP requests.
233+func WithHTTPServer(srv *http.Server) SSEOption {
234+ return func(s *SSEServer) {
235+ s.srv = srv
236+ }
237+}
238+
239+func WithKeepAliveInterval(keepAliveInterval time.Duration) SSEOption {
240+ return func(s *SSEServer) {
241+ s.keepAlive = true
242+ s.keepAliveInterval = keepAliveInterval
243+ }
244+}
245+
246+func WithKeepAlive(keepAlive bool) SSEOption {
247+ return func(s *SSEServer) {
248+ s.keepAlive = keepAlive
249+ }
250+}
251+
252+// WithSSEContextFunc sets a function that will be called to customise the context
253+// to the server using the incoming request.
254+func WithSSEContextFunc(fn SSEContextFunc) SSEOption {
255+ return func(s *SSEServer) {
256+ s.contextFunc = fn
257+ }
258+}
259+
260+// NewSSEServer creates a new SSE server instance with the given MCP server and options.
261+func NewSSEServer(server *MCPServer, opts ...SSEOption) *SSEServer {
262+ s := &SSEServer{
263+ server: server,
264+ sseEndpoint: "/sse",
265+ messageEndpoint: "/message",
266+ useFullURLForMessageEndpoint: true,
267+ keepAlive: false,
268+ keepAliveInterval: 10 * time.Second,
269+ }
270+
271+ // Apply all options
272+ for _, opt := range opts {
273+ opt(s)
274+ }
275+
276+ return s
277+}
278+
279+// NewTestServer creates a test server for testing purposes
280+func NewTestServer(server *MCPServer, opts ...SSEOption) *httptest.Server {
281+ sseServer := NewSSEServer(server, opts...)
282+
283+ testServer := httptest.NewServer(sseServer)
284+ sseServer.baseURL = testServer.URL
285+ return testServer
286+}
287+
288+// Start begins serving SSE connections on the specified address.
289+// It sets up HTTP handlers for SSE and message endpoints.
290+func (s *SSEServer) Start(addr string) error {
291+ s.mu.Lock()
292+ if s.srv == nil {
293+ s.srv = &http.Server{
294+ Addr: addr,
295+ Handler: s,
296+ }
297+ } else {
298+ if s.srv.Addr == "" {
299+ s.srv.Addr = addr
300+ } else if s.srv.Addr != addr {
301+ return fmt.Errorf("conflicting listen address: WithHTTPServer(%q) vs Start(%q)", s.srv.Addr, addr)
302+ }
303+ }
304+ srv := s.srv
305+ s.mu.Unlock()
306+
307+ return srv.ListenAndServe()
308+}
309+
310+// Shutdown gracefully stops the SSE server, closing all active sessions
311+// and shutting down the HTTP server.
312+func (s *SSEServer) Shutdown(ctx context.Context) error {
313+ s.mu.RLock()
314+ srv := s.srv
315+ s.mu.RUnlock()
316+
317+ if srv != nil {
318+ s.sessions.Range(func(key, value any) bool {
319+ if session, ok := value.(*sseSession); ok {
320+ close(session.done)
321+ }
322+ s.sessions.Delete(key)
323+ return true
324+ })
325+
326+ return srv.Shutdown(ctx)
327+ }
328+ return nil
329+}
330+
331+// handleSSE handles incoming SSE connection requests.
332+// It sets up appropriate headers and creates a new session for the client.
333+func (s *SSEServer) handleSSE(w http.ResponseWriter, r *http.Request) {
334+ if r.Method != http.MethodGet {
335+ http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
336+ return
337+ }
338+
339+ w.Header().Set("Content-Type", "text/event-stream")
340+ w.Header().Set("Cache-Control", "no-cache")
341+ w.Header().Set("Connection", "keep-alive")
342+ w.Header().Set("Access-Control-Allow-Origin", "*")
343+
344+ flusher, ok := w.(http.Flusher)
345+ if !ok {
346+ http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
347+ return
348+ }
349+
350+ sessionID := uuid.New().String()
351+ session := &sseSession{
352+ done: make(chan struct{}),
353+ eventQueue: make(chan string, 100), // Buffer for events
354+ sessionID: sessionID,
355+ notificationChannel: make(chan mcp.JSONRPCNotification, 100),
356+ }
357+
358+ s.sessions.Store(sessionID, session)
359+ defer s.sessions.Delete(sessionID)
360+
361+ if err := s.server.RegisterSession(r.Context(), session); err != nil {
362+ http.Error(
363+ w,
364+ fmt.Sprintf("Session registration failed: %v", err),
365+ http.StatusInternalServerError,
366+ )
367+ return
368+ }
369+ defer s.server.UnregisterSession(r.Context(), sessionID)
370+
371+ // Start notification handler for this session
372+ go func() {
373+ for {
374+ select {
375+ case notification := <-session.notificationChannel:
376+ eventData, err := json.Marshal(notification)
377+ if err == nil {
378+ select {
379+ case session.eventQueue <- fmt.Sprintf("event: message\ndata: %s\n\n", eventData):
380+ // Event queued successfully
381+ case <-session.done:
382+ return
383+ }
384+ }
385+ case <-session.done:
386+ return
387+ case <-r.Context().Done():
388+ return
389+ }
390+ }
391+ }()
392+
393+ // Start keep alive : ping
394+ if s.keepAlive {
395+ go func() {
396+ ticker := time.NewTicker(s.keepAliveInterval)
397+ defer ticker.Stop()
398+ for {
399+ select {
400+ case <-ticker.C:
401+ message := mcp.JSONRPCRequest{
402+ JSONRPC: "2.0",
403+ ID: mcp.NewRequestId(session.requestID.Add(1)),
404+ Request: mcp.Request{
405+ Method: "ping",
406+ },
407+ }
408+ messageBytes, _ := json.Marshal(message)
409+ pingMsg := fmt.Sprintf("event: message\ndata:%s\n\n", messageBytes)
410+ select {
411+ case session.eventQueue <- pingMsg:
412+ // Message sent successfully
413+ case <-session.done:
414+ return
415+ }
416+ case <-session.done:
417+ return
418+ case <-r.Context().Done():
419+ return
420+ }
421+ }
422+ }()
423+ }
424+
425+ // Send the initial endpoint event
426+ endpoint := s.GetMessageEndpointForClient(r, sessionID)
427+ if s.appendQueryToMessageEndpoint && len(r.URL.RawQuery) > 0 {
428+ endpoint += "&" + r.URL.RawQuery
429+ }
430+ fmt.Fprintf(w, "event: endpoint\ndata: %s\r\n\r\n", endpoint)
431+ flusher.Flush()
432+
433+ // Main event loop - this runs in the HTTP handler goroutine
434+ for {
435+ select {
436+ case event := <-session.eventQueue:
437+ // Write the event to the response
438+ fmt.Fprint(w, event)
439+ flusher.Flush()
440+ case <-r.Context().Done():
441+ close(session.done)
442+ return
443+ case <-session.done:
444+ return
445+ }
446+ }
447+}
448+
449+// GetMessageEndpointForClient returns the appropriate message endpoint URL with session ID
450+// for the given request. This is the canonical way to compute the message endpoint for a client.
451+// It handles both dynamic and static path modes, and honors the WithUseFullURLForMessageEndpoint flag.
452+func (s *SSEServer) GetMessageEndpointForClient(r *http.Request, sessionID string) string {
453+ basePath := s.basePath
454+ if s.dynamicBasePathFunc != nil {
455+ basePath = s.dynamicBasePathFunc(r, sessionID)
456+ }
457+
458+ endpointPath := normalizeURLPath(basePath, s.messageEndpoint)
459+ if s.useFullURLForMessageEndpoint && s.baseURL != "" {
460+ endpointPath = s.baseURL + endpointPath
461+ }
462+
463+ return fmt.Sprintf("%s?sessionId=%s", endpointPath, sessionID)
464+}
465+
466+// handleMessage processes incoming JSON-RPC messages from clients and sends responses
467+// back through the SSE connection and 202 code to HTTP response.
468+func (s *SSEServer) handleMessage(w http.ResponseWriter, r *http.Request) {
469+ if r.Method != http.MethodPost {
470+ s.writeJSONRPCError(w, nil, mcp.INVALID_REQUEST, "Method not allowed")
471+ return
472+ }
473+
474+ sessionID := r.URL.Query().Get("sessionId")
475+ if sessionID == "" {
476+ s.writeJSONRPCError(w, nil, mcp.INVALID_PARAMS, "Missing sessionId")
477+ return
478+ }
479+ sessionI, ok := s.sessions.Load(sessionID)
480+ if !ok {
481+ s.writeJSONRPCError(w, nil, mcp.INVALID_PARAMS, "Invalid session ID")
482+ return
483+ }
484+ session := sessionI.(*sseSession)
485+
486+ // Set the client context before handling the message
487+ ctx := s.server.WithContext(r.Context(), session)
488+ if s.contextFunc != nil {
489+ ctx = s.contextFunc(ctx, r)
490+ }
491+
492+ // Parse message as raw JSON
493+ var rawMessage json.RawMessage
494+ if err := json.NewDecoder(r.Body).Decode(&rawMessage); err != nil {
495+ s.writeJSONRPCError(w, nil, mcp.PARSE_ERROR, "Parse error")
496+ return
497+ }
498+
499+ // Create a context that preserves all values from parent ctx but won't be canceled when the parent is canceled.
500+ // this is required because the http ctx will be canceled when the client disconnects
501+ detachedCtx := context.WithoutCancel(ctx)
502+
503+ // quick return request, send 202 Accepted with no body, then deal the message and sent response via SSE
504+ w.WriteHeader(http.StatusAccepted)
505+
506+ // Create a new context for handling the message that will be canceled when the message handling is done
507+ messageCtx, cancel := context.WithCancel(detachedCtx)
508+
509+ go func(ctx context.Context) {
510+ defer cancel()
511+ // Use the context that will be canceled when session is done
512+ // Process message through MCPServer
513+ response := s.server.HandleMessage(ctx, rawMessage)
514+ // Only send response if there is one (not for notifications)
515+ if response != nil {
516+ var message string
517+ if eventData, err := json.Marshal(response); err != nil {
518+ // If there is an error marshalling the response, send a generic error response
519+ log.Printf("failed to marshal response: %v", err)
520+ message = "event: message\ndata: {\"error\": \"internal error\",\"jsonrpc\": \"2.0\", \"id\": null}\n\n"
521+ } else {
522+ message = fmt.Sprintf("event: message\ndata: %s\n\n", eventData)
523+ }
524+
525+ // Queue the event for sending via SSE
526+ select {
527+ case session.eventQueue <- message:
528+ // Event queued successfully
529+ case <-session.done:
530+ // Session is closed, don't try to queue
531+ default:
532+ // Queue is full, log this situation
533+ log.Printf("Event queue full for session %s", sessionID)
534+ }
535+ }
536+ }(messageCtx)
537+}
538+
539+// writeJSONRPCError writes a JSON-RPC error response with the given error details.
540+func (s *SSEServer) writeJSONRPCError(
541+ w http.ResponseWriter,
542+ id any,
543+ code int,
544+ message string,
545+) {
546+ response := createErrorResponse(id, code, message)
547+ w.Header().Set("Content-Type", "application/json")
548+ w.WriteHeader(http.StatusBadRequest)
549+ if err := json.NewEncoder(w).Encode(response); err != nil {
550+ http.Error(
551+ w,
552+ fmt.Sprintf("Failed to encode response: %v", err),
553+ http.StatusInternalServerError,
554+ )
555+ return
556+ }
557+}
558+
559+// SendEventToSession sends an event to a specific SSE session identified by sessionID.
560+// Returns an error if the session is not found or closed.
561+func (s *SSEServer) SendEventToSession(
562+ sessionID string,
563+ event any,
564+) error {
565+ sessionI, ok := s.sessions.Load(sessionID)
566+ if !ok {
567+ return fmt.Errorf("session not found: %s", sessionID)
568+ }
569+ session := sessionI.(*sseSession)
570+
571+ eventData, err := json.Marshal(event)
572+ if err != nil {
573+ return err
574+ }
575+
576+ // Queue the event for sending via SSE
577+ select {
578+ case session.eventQueue <- fmt.Sprintf("event: message\ndata: %s\n\n", eventData):
579+ return nil
580+ case <-session.done:
581+ return fmt.Errorf("session closed")
582+ default:
583+ return fmt.Errorf("event queue full")
584+ }
585+}
586+
587+func (s *SSEServer) GetUrlPath(input string) (string, error) {
588+ parse, err := url.Parse(input)
589+ if err != nil {
590+ return "", fmt.Errorf("failed to parse URL %s: %w", input, err)
591+ }
592+ return parse.Path, nil
593+}
594+
595+func (s *SSEServer) CompleteSseEndpoint() (string, error) {
596+ if s.dynamicBasePathFunc != nil {
597+ return "", &ErrDynamicPathConfig{Method: "CompleteSseEndpoint"}
598+ }
599+
600+ path := normalizeURLPath(s.basePath, s.sseEndpoint)
601+ return s.baseURL + path, nil
602+}
603+
604+func (s *SSEServer) CompleteSsePath() string {
605+ path, err := s.CompleteSseEndpoint()
606+ if err != nil {
607+ return normalizeURLPath(s.basePath, s.sseEndpoint)
608+ }
609+ urlPath, err := s.GetUrlPath(path)
610+ if err != nil {
611+ return normalizeURLPath(s.basePath, s.sseEndpoint)
612+ }
613+ return urlPath
614+}
615+
616+func (s *SSEServer) CompleteMessageEndpoint() (string, error) {
617+ if s.dynamicBasePathFunc != nil {
618+ return "", &ErrDynamicPathConfig{Method: "CompleteMessageEndpoint"}
619+ }
620+ path := normalizeURLPath(s.basePath, s.messageEndpoint)
621+ return s.baseURL + path, nil
622+}
623+
624+func (s *SSEServer) CompleteMessagePath() string {
625+ path, err := s.CompleteMessageEndpoint()
626+ if err != nil {
627+ return normalizeURLPath(s.basePath, s.messageEndpoint)
628+ }
629+ urlPath, err := s.GetUrlPath(path)
630+ if err != nil {
631+ return normalizeURLPath(s.basePath, s.messageEndpoint)
632+ }
633+ return urlPath
634+}
635+
636+// SSEHandler returns an http.Handler for the SSE endpoint.
637+//
638+// This method allows you to mount the SSE handler at any arbitrary path
639+// using your own router (e.g. net/http, gorilla/mux, chi, etc.). It is
640+// intended for advanced scenarios where you want to control the routing or
641+// support dynamic segments.
642+//
643+// IMPORTANT: When using this handler in advanced/dynamic mounting scenarios,
644+// you must use the WithDynamicBasePath option to ensure the correct base path
645+// is communicated to clients.
646+//
647+// Example usage:
648+//
649+// // Advanced/dynamic:
650+// sseServer := NewSSEServer(mcpServer,
651+// WithDynamicBasePath(func(r *http.Request, sessionID string) string {
652+// tenant := r.PathValue("tenant")
653+// return "/mcp/" + tenant
654+// }),
655+// WithBaseURL("http://localhost:8080")
656+// )
657+// mux.Handle("/mcp/{tenant}/sse", sseServer.SSEHandler())
658+// mux.Handle("/mcp/{tenant}/message", sseServer.MessageHandler())
659+//
660+// For non-dynamic cases, use ServeHTTP method instead.
661+func (s *SSEServer) SSEHandler() http.Handler {
662+ return http.HandlerFunc(s.handleSSE)
663+}
664+
665+// MessageHandler returns an http.Handler for the message endpoint.
666+//
667+// This method allows you to mount the message handler at any arbitrary path
668+// using your own router (e.g. net/http, gorilla/mux, chi, etc.). It is
669+// intended for advanced scenarios where you want to control the routing or
670+// support dynamic segments.
671+//
672+// IMPORTANT: When using this handler in advanced/dynamic mounting scenarios,
673+// you must use the WithDynamicBasePath option to ensure the correct base path
674+// is communicated to clients.
675+//
676+// Example usage:
677+//
678+// // Advanced/dynamic:
679+// sseServer := NewSSEServer(mcpServer,
680+// WithDynamicBasePath(func(r *http.Request, sessionID string) string {
681+// tenant := r.PathValue("tenant")
682+// return "/mcp/" + tenant
683+// }),
684+// WithBaseURL("http://localhost:8080")
685+// )
686+// mux.Handle("/mcp/{tenant}/sse", sseServer.SSEHandler())
687+// mux.Handle("/mcp/{tenant}/message", sseServer.MessageHandler())
688+//
689+// For non-dynamic cases, use ServeHTTP method instead.
690+func (s *SSEServer) MessageHandler() http.Handler {
691+ return http.HandlerFunc(s.handleMessage)
692+}
693+
694+// ServeHTTP implements the http.Handler interface.
695+func (s *SSEServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
696+ if s.dynamicBasePathFunc != nil {
697+ http.Error(
698+ w,
699+ (&ErrDynamicPathConfig{Method: "ServeHTTP"}).Error(),
700+ http.StatusInternalServerError,
701+ )
702+ return
703+ }
704+ path := r.URL.Path
705+ // Use exact path matching rather than Contains
706+ ssePath := s.CompleteSsePath()
707+ if ssePath != "" && path == ssePath {
708+ s.handleSSE(w, r)
709+ return
710+ }
711+ messagePath := s.CompleteMessagePath()
712+ if messagePath != "" && path == messagePath {
713+ s.handleMessage(w, r)
714+ return
715+ }
716+
717+ http.NotFound(w, r)
718+}
719+
720+// normalizeURLPath joins path elements like path.Join but ensures the
721+// result always starts with a leading slash and never ends with a slash
722+func normalizeURLPath(elem ...string) string {
723+ joined := path.Join(elem...)
724+
725+ // Ensure leading slash
726+ if !strings.HasPrefix(joined, "/") {
727+ joined = "/" + joined
728+ }
729+
730+ // Remove trailing slash if not just "/"
731+ if len(joined) > 1 && strings.HasSuffix(joined, "/") {
732+ joined = joined[:len(joined)-1]
733+ }
734+
735+ return joined
736+}
vendor/github.com/mark3labs/mcp-go/server/stdio.gonew file+314
@@ -0,0 +1,314 @@
1+package server
2+
3+import (
4+ "bufio"
5+ "context"
6+ "encoding/json"
7+ "fmt"
8+ "io"
9+ "log"
10+ "os"
11+ "os/signal"
12+ "sync/atomic"
13+ "syscall"
14+
15+ "github.com/mark3labs/mcp-go/mcp"
16+)
17+
18+// StdioContextFunc is a function that takes an existing context and returns
19+// a potentially modified context.
20+// This can be used to inject context values from environment variables,
21+// for example.
22+type StdioContextFunc func(ctx context.Context) context.Context
23+
24+// StdioServer wraps a MCPServer and handles stdio communication.
25+// It provides a simple way to create command-line MCP servers that
26+// communicate via standard input/output streams using JSON-RPC messages.
27+type StdioServer struct {
28+ server *MCPServer
29+ errLogger *log.Logger
30+ contextFunc StdioContextFunc
31+}
32+
33+// StdioOption defines a function type for configuring StdioServer
34+type StdioOption func(*StdioServer)
35+
36+// WithErrorLogger sets the error logger for the server
37+func WithErrorLogger(logger *log.Logger) StdioOption {
38+ return func(s *StdioServer) {
39+ s.errLogger = logger
40+ }
41+}
42+
43+// WithStdioContextFunc sets a function that will be called to customise the context
44+// to the server. Note that the stdio server uses the same context for all requests,
45+// so this function will only be called once per server instance.
46+func WithStdioContextFunc(fn StdioContextFunc) StdioOption {
47+ return func(s *StdioServer) {
48+ s.contextFunc = fn
49+ }
50+}
51+
52+// stdioSession is a static client session, since stdio has only one client.
53+type stdioSession struct {
54+ notifications chan mcp.JSONRPCNotification
55+ initialized atomic.Bool
56+ loggingLevel atomic.Value
57+ clientInfo atomic.Value // stores session-specific client info
58+}
59+
60+func (s *stdioSession) SessionID() string {
61+ return "stdio"
62+}
63+
64+func (s *stdioSession) NotificationChannel() chan<- mcp.JSONRPCNotification {
65+ return s.notifications
66+}
67+
68+func (s *stdioSession) Initialize() {
69+ // set default logging level
70+ s.loggingLevel.Store(mcp.LoggingLevelError)
71+ s.initialized.Store(true)
72+}
73+
74+func (s *stdioSession) Initialized() bool {
75+ return s.initialized.Load()
76+}
77+
78+func (s *stdioSession) GetClientInfo() mcp.Implementation {
79+ if value := s.clientInfo.Load(); value != nil {
80+ if clientInfo, ok := value.(mcp.Implementation); ok {
81+ return clientInfo
82+ }
83+ }
84+ return mcp.Implementation{}
85+}
86+
87+func (s *stdioSession) SetClientInfo(clientInfo mcp.Implementation) {
88+ s.clientInfo.Store(clientInfo)
89+}
90+
91+func (s *stdioSession) SetLogLevel(level mcp.LoggingLevel) {
92+ s.loggingLevel.Store(level)
93+}
94+
95+func (s *stdioSession) GetLogLevel() mcp.LoggingLevel {
96+ level := s.loggingLevel.Load()
97+ if level == nil {
98+ return mcp.LoggingLevelError
99+ }
100+ return level.(mcp.LoggingLevel)
101+}
102+
103+var (
104+ _ ClientSession = (*stdioSession)(nil)
105+ _ SessionWithLogging = (*stdioSession)(nil)
106+ _ SessionWithClientInfo = (*stdioSession)(nil)
107+)
108+
109+var stdioSessionInstance = stdioSession{
110+ notifications: make(chan mcp.JSONRPCNotification, 100),
111+}
112+
113+// NewStdioServer creates a new stdio server wrapper around an MCPServer.
114+// It initializes the server with a default error logger that discards all output.
115+func NewStdioServer(server *MCPServer) *StdioServer {
116+ return &StdioServer{
117+ server: server,
118+ errLogger: log.New(
119+ os.Stderr,
120+ "",
121+ log.LstdFlags,
122+ ), // Default to discarding logs
123+ }
124+}
125+
126+// SetErrorLogger configures where error messages from the StdioServer are logged.
127+// The provided logger will receive all error messages generated during server operation.
128+func (s *StdioServer) SetErrorLogger(logger *log.Logger) {
129+ s.errLogger = logger
130+}
131+
132+// SetContextFunc sets a function that will be called to customise the context
133+// to the server. Note that the stdio server uses the same context for all requests,
134+// so this function will only be called once per server instance.
135+func (s *StdioServer) SetContextFunc(fn StdioContextFunc) {
136+ s.contextFunc = fn
137+}
138+
139+// handleNotifications continuously processes notifications from the session's notification channel
140+// and writes them to the provided output. It runs until the context is cancelled.
141+// Any errors encountered while writing notifications are logged but do not stop the handler.
142+func (s *StdioServer) handleNotifications(ctx context.Context, stdout io.Writer) {
143+ for {
144+ select {
145+ case notification := <-stdioSessionInstance.notifications:
146+ if err := s.writeResponse(notification, stdout); err != nil {
147+ s.errLogger.Printf("Error writing notification: %v", err)
148+ }
149+ case <-ctx.Done():
150+ return
151+ }
152+ }
153+}
154+
155+// processInputStream continuously reads and processes messages from the input stream.
156+// It handles EOF gracefully as a normal termination condition.
157+// The function returns when either:
158+// - The context is cancelled (returns context.Err())
159+// - EOF is encountered (returns nil)
160+// - An error occurs while reading or processing messages (returns the error)
161+func (s *StdioServer) processInputStream(ctx context.Context, reader *bufio.Reader, stdout io.Writer) error {
162+ for {
163+ if err := ctx.Err(); err != nil {
164+ return err
165+ }
166+
167+ line, err := s.readNextLine(ctx, reader)
168+ if err != nil {
169+ if err == io.EOF {
170+ return nil
171+ }
172+ s.errLogger.Printf("Error reading input: %v", err)
173+ return err
174+ }
175+
176+ if err := s.processMessage(ctx, line, stdout); err != nil {
177+ if err == io.EOF {
178+ return nil
179+ }
180+ s.errLogger.Printf("Error handling message: %v", err)
181+ return err
182+ }
183+ }
184+}
185+
186+// readNextLine reads a single line from the input reader in a context-aware manner.
187+// It uses channels to make the read operation cancellable via context.
188+// Returns the read line and any error encountered. If the context is cancelled,
189+// returns an empty string and the context's error. EOF is returned when the input
190+// stream is closed.
191+func (s *StdioServer) readNextLine(ctx context.Context, reader *bufio.Reader) (string, error) {
192+ type result struct {
193+ line string
194+ err error
195+ }
196+
197+ resultCh := make(chan result, 1)
198+
199+ go func() {
200+ line, err := reader.ReadString('\n')
201+ resultCh <- result{line: line, err: err}
202+ }()
203+
204+ select {
205+ case <-ctx.Done():
206+ return "", nil
207+ case res := <-resultCh:
208+ return res.line, res.err
209+ }
210+}
211+
212+// Listen starts listening for JSON-RPC messages on the provided input and writes responses to the provided output.
213+// It runs until the context is cancelled or an error occurs.
214+// Returns an error if there are issues with reading input or writing output.
215+func (s *StdioServer) Listen(
216+ ctx context.Context,
217+ stdin io.Reader,
218+ stdout io.Writer,
219+) error {
220+ // Set a static client context since stdio only has one client
221+ if err := s.server.RegisterSession(ctx, &stdioSessionInstance); err != nil {
222+ return fmt.Errorf("register session: %w", err)
223+ }
224+ defer s.server.UnregisterSession(ctx, stdioSessionInstance.SessionID())
225+ ctx = s.server.WithContext(ctx, &stdioSessionInstance)
226+
227+ // Add in any custom context.
228+ if s.contextFunc != nil {
229+ ctx = s.contextFunc(ctx)
230+ }
231+
232+ reader := bufio.NewReader(stdin)
233+
234+ // Start notification handler
235+ go s.handleNotifications(ctx, stdout)
236+ return s.processInputStream(ctx, reader, stdout)
237+}
238+
239+// processMessage handles a single JSON-RPC message and writes the response.
240+// It parses the message, processes it through the wrapped MCPServer, and writes any response.
241+// Returns an error if there are issues with message processing or response writing.
242+func (s *StdioServer) processMessage(
243+ ctx context.Context,
244+ line string,
245+ writer io.Writer,
246+) error {
247+ // If line is empty, likely due to ctx cancellation
248+ if len(line) == 0 {
249+ return nil
250+ }
251+
252+ // Parse the message as raw JSON
253+ var rawMessage json.RawMessage
254+ if err := json.Unmarshal([]byte(line), &rawMessage); err != nil {
255+ response := createErrorResponse(nil, mcp.PARSE_ERROR, "Parse error")
256+ return s.writeResponse(response, writer)
257+ }
258+
259+ // Handle the message using the wrapped server
260+ response := s.server.HandleMessage(ctx, rawMessage)
261+
262+ // Only write response if there is one (not for notifications)
263+ if response != nil {
264+ if err := s.writeResponse(response, writer); err != nil {
265+ return fmt.Errorf("failed to write response: %w", err)
266+ }
267+ }
268+
269+ return nil
270+}
271+
272+// writeResponse marshals and writes a JSON-RPC response message followed by a newline.
273+// Returns an error if marshaling or writing fails.
274+func (s *StdioServer) writeResponse(
275+ response mcp.JSONRPCMessage,
276+ writer io.Writer,
277+) error {
278+ responseBytes, err := json.Marshal(response)
279+ if err != nil {
280+ return err
281+ }
282+
283+ // Write response followed by newline
284+ if _, err := fmt.Fprintf(writer, "%s\n", responseBytes); err != nil {
285+ return err
286+ }
287+
288+ return nil
289+}
290+
291+// ServeStdio is a convenience function that creates and starts a StdioServer with os.Stdin and os.Stdout.
292+// It sets up signal handling for graceful shutdown on SIGTERM and SIGINT.
293+// Returns an error if the server encounters any issues during operation.
294+func ServeStdio(server *MCPServer, opts ...StdioOption) error {
295+ s := NewStdioServer(server)
296+
297+ for _, opt := range opts {
298+ opt(s)
299+ }
300+
301+ ctx, cancel := context.WithCancel(context.Background())
302+ defer cancel()
303+
304+ // Set up signal handling
305+ sigChan := make(chan os.Signal, 1)
306+ signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
307+
308+ go func() {
309+ <-sigChan
310+ cancel()
311+ }()
312+
313+ return s.Listen(ctx, os.Stdin, os.Stdout)
314+}
vendor/github.com/mark3labs/mcp-go/server/streamable_http.gonew file+653
@@ -0,0 +1,653 @@
1+package server
2+
3+import (
4+ "context"
5+ "encoding/json"
6+ "fmt"
7+ "io"
8+ "net/http"
9+ "net/http/httptest"
10+ "strings"
11+ "sync"
12+ "sync/atomic"
13+ "time"
14+
15+ "github.com/google/uuid"
16+ "github.com/mark3labs/mcp-go/mcp"
17+ "github.com/mark3labs/mcp-go/util"
18+)
19+
20+// StreamableHTTPOption defines a function type for configuring StreamableHTTPServer
21+type StreamableHTTPOption func(*StreamableHTTPServer)
22+
23+// WithEndpointPath sets the endpoint path for the server.
24+// The default is "/mcp".
25+// It's only works for `Start` method. When used as a http.Handler, it has no effect.
26+func WithEndpointPath(endpointPath string) StreamableHTTPOption {
27+ return func(s *StreamableHTTPServer) {
28+ // Normalize the endpoint path to ensure it starts with a slash and doesn't end with one
29+ normalizedPath := "/" + strings.Trim(endpointPath, "/")
30+ s.endpointPath = normalizedPath
31+ }
32+}
33+
34+// WithStateLess sets the server to stateless mode.
35+// If true, the server will manage no session information. Every request will be treated
36+// as a new session. No session id returned to the client.
37+// The default is false.
38+//
39+// Notice: This is a convenience method. It's identical to set WithSessionIdManager option
40+// to StatelessSessionIdManager.
41+func WithStateLess(stateLess bool) StreamableHTTPOption {
42+ return func(s *StreamableHTTPServer) {
43+ s.sessionIdManager = &StatelessSessionIdManager{}
44+ }
45+}
46+
47+// WithSessionIdManager sets a custom session id generator for the server.
48+// By default, the server will use SimpleStatefulSessionIdGenerator, which generates
49+// session ids with uuid, and it's insecure.
50+// Notice: it will override the WithStateLess option.
51+func WithSessionIdManager(manager SessionIdManager) StreamableHTTPOption {
52+ return func(s *StreamableHTTPServer) {
53+ s.sessionIdManager = manager
54+ }
55+}
56+
57+// WithHeartbeatInterval sets the heartbeat interval. Positive interval means the
58+// server will send a heartbeat to the client through the GET connection, to keep
59+// the connection alive from being closed by the network infrastructure (e.g.
60+// gateways). If the client does not establish a GET connection, it has no
61+// effect. The default is not to send heartbeats.
62+func WithHeartbeatInterval(interval time.Duration) StreamableHTTPOption {
63+ return func(s *StreamableHTTPServer) {
64+ s.listenHeartbeatInterval = interval
65+ }
66+}
67+
68+// WithHTTPContextFunc sets a function that will be called to customise the context
69+// to the server using the incoming request.
70+// This can be used to inject context values from headers, for example.
71+func WithHTTPContextFunc(fn HTTPContextFunc) StreamableHTTPOption {
72+ return func(s *StreamableHTTPServer) {
73+ s.contextFunc = fn
74+ }
75+}
76+
77+// WithStreamableHTTPServer sets the HTTP server instance for StreamableHTTPServer.
78+// NOTE: When providing a custom HTTP server, you must handle routing yourself
79+// If routing is not set up, the server will start but won't handle any MCP requests.
80+func WithStreamableHTTPServer(srv *http.Server) StreamableHTTPOption {
81+ return func(s *StreamableHTTPServer) {
82+ s.httpServer = srv
83+ }
84+}
85+
86+// WithLogger sets the logger for the server
87+func WithLogger(logger util.Logger) StreamableHTTPOption {
88+ return func(s *StreamableHTTPServer) {
89+ s.logger = logger
90+ }
91+}
92+
93+// StreamableHTTPServer implements a Streamable-http based MCP server.
94+// It communicates with clients over HTTP protocol, supporting both direct HTTP responses, and SSE streams.
95+// https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http
96+//
97+// Usage:
98+//
99+// server := NewStreamableHTTPServer(mcpServer)
100+// server.Start(":8080") // The final url for client is http://xxxx:8080/mcp by default
101+//
102+// or the server itself can be used as a http.Handler, which is convenient to
103+// integrate with existing http servers, or advanced usage:
104+//
105+// handler := NewStreamableHTTPServer(mcpServer)
106+// http.Handle("/streamable-http", handler)
107+// http.ListenAndServe(":8080", nil)
108+//
109+// Notice:
110+// Except for the GET handlers(listening), the POST handlers(request/notification) will
111+// not trigger the session registration. So the methods like `SendNotificationToSpecificClient`
112+// or `hooks.onRegisterSession` will not be triggered for POST messages.
113+//
114+// The current implementation does not support the following features from the specification:
115+// - Batching of requests/notifications/responses in arrays.
116+// - Stream Resumability
117+type StreamableHTTPServer struct {
118+ server *MCPServer
119+ sessionTools *sessionToolsStore
120+ sessionRequestIDs sync.Map // sessionId --> last requestID(*atomic.Int64)
121+
122+ httpServer *http.Server
123+ mu sync.RWMutex
124+
125+ endpointPath string
126+ contextFunc HTTPContextFunc
127+ sessionIdManager SessionIdManager
128+ listenHeartbeatInterval time.Duration
129+ logger util.Logger
130+}
131+
132+// NewStreamableHTTPServer creates a new streamable-http server instance
133+func NewStreamableHTTPServer(server *MCPServer, opts ...StreamableHTTPOption) *StreamableHTTPServer {
134+ s := &StreamableHTTPServer{
135+ server: server,
136+ sessionTools: newSessionToolsStore(),
137+ endpointPath: "/mcp",
138+ sessionIdManager: &InsecureStatefulSessionIdManager{},
139+ logger: util.DefaultLogger(),
140+ }
141+
142+ // Apply all options
143+ for _, opt := range opts {
144+ opt(s)
145+ }
146+ return s
147+}
148+
149+// ServeHTTP implements the http.Handler interface.
150+func (s *StreamableHTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
151+ switch r.Method {
152+ case http.MethodPost:
153+ s.handlePost(w, r)
154+ case http.MethodGet:
155+ s.handleGet(w, r)
156+ case http.MethodDelete:
157+ s.handleDelete(w, r)
158+ default:
159+ http.NotFound(w, r)
160+ }
161+}
162+
163+// Start begins serving the http server on the specified address and path
164+// (endpointPath). like:
165+//
166+// s.Start(":8080")
167+func (s *StreamableHTTPServer) Start(addr string) error {
168+ s.mu.Lock()
169+ if s.httpServer == nil {
170+ mux := http.NewServeMux()
171+ mux.Handle(s.endpointPath, s)
172+ s.httpServer = &http.Server{
173+ Addr: addr,
174+ Handler: mux,
175+ }
176+ } else {
177+ if s.httpServer.Addr == "" {
178+ s.httpServer.Addr = addr
179+ } else if s.httpServer.Addr != addr {
180+ return fmt.Errorf("conflicting listen address: WithStreamableHTTPServer(%q) vs Start(%q)", s.httpServer.Addr, addr)
181+ }
182+ }
183+ srv := s.httpServer
184+ s.mu.Unlock()
185+
186+ return srv.ListenAndServe()
187+}
188+
189+// Shutdown gracefully stops the server, closing all active sessions
190+// and shutting down the HTTP server.
191+func (s *StreamableHTTPServer) Shutdown(ctx context.Context) error {
192+
193+ // shutdown the server if needed (may use as a http.Handler)
194+ s.mu.RLock()
195+ srv := s.httpServer
196+ s.mu.RUnlock()
197+ if srv != nil {
198+ return srv.Shutdown(ctx)
199+ }
200+ return nil
201+}
202+
203+// --- internal methods ---
204+
205+const (
206+ headerKeySessionID = "Mcp-Session-Id"
207+)
208+
209+func (s *StreamableHTTPServer) handlePost(w http.ResponseWriter, r *http.Request) {
210+ // post request carry request/notification message
211+
212+ // Check content type
213+ contentType := r.Header.Get("Content-Type")
214+ if contentType != "application/json" {
215+ http.Error(w, "Invalid content type: must be 'application/json'", http.StatusBadRequest)
216+ return
217+ }
218+
219+ // Check the request body is valid json, meanwhile, get the request Method
220+ rawData, err := io.ReadAll(r.Body)
221+ if err != nil {
222+ s.writeJSONRPCError(w, nil, mcp.PARSE_ERROR, fmt.Sprintf("read request body error: %v", err))
223+ return
224+ }
225+ var baseMessage struct {
226+ Method mcp.MCPMethod `json:"method"`
227+ }
228+ if err := json.Unmarshal(rawData, &baseMessage); err != nil {
229+ s.writeJSONRPCError(w, nil, mcp.PARSE_ERROR, "request body is not valid json")
230+ return
231+ }
232+ isInitializeRequest := baseMessage.Method == mcp.MethodInitialize
233+
234+ // Prepare the session for the mcp server
235+ // The session is ephemeral. Its life is the same as the request. It's only created
236+ // for interaction with the mcp server.
237+ var sessionID string
238+ if isInitializeRequest {
239+ // generate a new one for initialize request
240+ sessionID = s.sessionIdManager.Generate()
241+ } else {
242+ // Get session ID from header.
243+ // Stateful servers need the client to carry the session ID.
244+ sessionID = r.Header.Get(headerKeySessionID)
245+ isTerminated, err := s.sessionIdManager.Validate(sessionID)
246+ if err != nil {
247+ http.Error(w, "Invalid session ID", http.StatusBadRequest)
248+ return
249+ }
250+ if isTerminated {
251+ http.Error(w, "Session terminated", http.StatusNotFound)
252+ return
253+ }
254+ }
255+
256+ session := newStreamableHttpSession(sessionID, s.sessionTools)
257+
258+ // Set the client context before handling the message
259+ ctx := s.server.WithContext(r.Context(), session)
260+ if s.contextFunc != nil {
261+ ctx = s.contextFunc(ctx, r)
262+ }
263+
264+ // handle potential notifications
265+ mu := sync.Mutex{}
266+ upgradedHeader := false
267+ done := make(chan struct{})
268+
269+ go func() {
270+ for {
271+ select {
272+ case nt := <-session.notificationChannel:
273+ func() {
274+ mu.Lock()
275+ defer mu.Unlock()
276+ // if the done chan is closed, as the request is terminated, just return
277+ select {
278+ case <-done:
279+ return
280+ default:
281+ }
282+ defer func() {
283+ flusher, ok := w.(http.Flusher)
284+ if ok {
285+ flusher.Flush()
286+ }
287+ }()
288+
289+ // if there's notifications, upgradedHeader to SSE response
290+ if !upgradedHeader {
291+ w.Header().Set("Content-Type", "text/event-stream")
292+ w.Header().Set("Connection", "keep-alive")
293+ w.Header().Set("Cache-Control", "no-cache")
294+ w.WriteHeader(http.StatusAccepted)
295+ upgradedHeader = true
296+ }
297+ err := writeSSEEvent(w, nt)
298+ if err != nil {
299+ s.logger.Errorf("Failed to write SSE event: %v", err)
300+ return
301+ }
302+ }()
303+ case <-done:
304+ return
305+ case <-ctx.Done():
306+ return
307+ }
308+ }
309+ }()
310+
311+ // Process message through MCPServer
312+ response := s.server.HandleMessage(ctx, rawData)
313+ if response == nil {
314+ // For notifications, just send 202 Accepted with no body
315+ w.WriteHeader(http.StatusAccepted)
316+ return
317+ }
318+
319+ // Write response
320+ mu.Lock()
321+ defer mu.Unlock()
322+ // close the done chan before unlock
323+ defer close(done)
324+ if ctx.Err() != nil {
325+ return
326+ }
327+ // If client-server communication already upgraded to SSE stream
328+ if session.upgradeToSSE.Load() {
329+ if !upgradedHeader {
330+ w.Header().Set("Content-Type", "text/event-stream")
331+ w.Header().Set("Connection", "keep-alive")
332+ w.Header().Set("Cache-Control", "no-cache")
333+ w.WriteHeader(http.StatusAccepted)
334+ upgradedHeader = true
335+ }
336+ if err := writeSSEEvent(w, response); err != nil {
337+ s.logger.Errorf("Failed to write final SSE response event: %v", err)
338+ }
339+ } else {
340+ w.Header().Set("Content-Type", "application/json")
341+ if isInitializeRequest && sessionID != "" {
342+ // send the session ID back to the client
343+ w.Header().Set(headerKeySessionID, sessionID)
344+ }
345+ w.WriteHeader(http.StatusOK)
346+ err := json.NewEncoder(w).Encode(response)
347+ if err != nil {
348+ s.logger.Errorf("Failed to write response: %v", err)
349+ }
350+ }
351+}
352+
353+func (s *StreamableHTTPServer) handleGet(w http.ResponseWriter, r *http.Request) {
354+ // get request is for listening to notifications
355+ // https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#listening-for-messages-from-the-server
356+
357+ sessionID := r.Header.Get(headerKeySessionID)
358+ // the specification didn't say we should validate the session id
359+
360+ if sessionID == "" {
361+ // It's a stateless server,
362+ // but the MCP server requires a unique ID for registering, so we use a random one
363+ sessionID = uuid.New().String()
364+ }
365+
366+ session := newStreamableHttpSession(sessionID, s.sessionTools)
367+ if err := s.server.RegisterSession(r.Context(), session); err != nil {
368+ http.Error(w, fmt.Sprintf("Session registration failed: %v", err), http.StatusBadRequest)
369+ return
370+ }
371+ defer s.server.UnregisterSession(r.Context(), sessionID)
372+
373+ // Set the client context before handling the message
374+ w.Header().Set("Content-Type", "text/event-stream")
375+ w.Header().Set("Cache-Control", "no-cache")
376+ w.Header().Set("Connection", "keep-alive")
377+ w.WriteHeader(http.StatusAccepted)
378+
379+ flusher, ok := w.(http.Flusher)
380+ if !ok {
381+ http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
382+ return
383+ }
384+ flusher.Flush()
385+
386+ // Start notification handler for this session
387+ done := make(chan struct{})
388+ defer close(done)
389+ writeChan := make(chan any, 16)
390+
391+ go func() {
392+ for {
393+ select {
394+ case nt := <-session.notificationChannel:
395+ select {
396+ case writeChan <- &nt:
397+ case <-done:
398+ return
399+ }
400+ case <-done:
401+ return
402+ }
403+ }
404+ }()
405+
406+ if s.listenHeartbeatInterval > 0 {
407+ // heartbeat to keep the connection alive
408+ go func() {
409+ ticker := time.NewTicker(s.listenHeartbeatInterval)
410+ defer ticker.Stop()
411+ for {
412+ select {
413+ case <-ticker.C:
414+ message := mcp.JSONRPCRequest{
415+ JSONRPC: "2.0",
416+ ID: mcp.NewRequestId(s.nextRequestID(sessionID)),
417+ Request: mcp.Request{
418+ Method: "ping",
419+ },
420+ }
421+ select {
422+ case writeChan <- message:
423+ case <-done:
424+ return
425+ }
426+ case <-done:
427+ return
428+ }
429+ }
430+ }()
431+ }
432+
433+ // Keep the connection open until the client disconnects
434+ //
435+ // There's will a Available() check when handler ends, and it maybe race with Flush(),
436+ // so we use a separate channel to send the data, inteading of flushing directly in other goroutine.
437+ for {
438+ select {
439+ case data := <-writeChan:
440+ if data == nil {
441+ continue
442+ }
443+ if err := writeSSEEvent(w, data); err != nil {
444+ s.logger.Errorf("Failed to write SSE event: %v", err)
445+ return
446+ }
447+ flusher.Flush()
448+ case <-r.Context().Done():
449+ return
450+ }
451+ }
452+}
453+
454+func (s *StreamableHTTPServer) handleDelete(w http.ResponseWriter, r *http.Request) {
455+ // delete request terminate the session
456+ sessionID := r.Header.Get(headerKeySessionID)
457+ notAllowed, err := s.sessionIdManager.Terminate(sessionID)
458+ if err != nil {
459+ http.Error(w, fmt.Sprintf("Session termination failed: %v", err), http.StatusInternalServerError)
460+ return
461+ }
462+ if notAllowed {
463+ http.Error(w, "Session termination not allowed", http.StatusMethodNotAllowed)
464+ return
465+ }
466+
467+ // remove the session relateddata from the sessionToolsStore
468+ s.sessionTools.delete(sessionID)
469+
470+ // remove current session's requstID information
471+ s.sessionRequestIDs.Delete(sessionID)
472+
473+ w.WriteHeader(http.StatusOK)
474+}
475+
476+func writeSSEEvent(w io.Writer, data any) error {
477+ jsonData, err := json.Marshal(data)
478+ if err != nil {
479+ return fmt.Errorf("failed to marshal data: %w", err)
480+ }
481+ _, err = fmt.Fprintf(w, "event: message\ndata: %s\n\n", jsonData)
482+ if err != nil {
483+ return fmt.Errorf("failed to write SSE event: %w", err)
484+ }
485+ return nil
486+}
487+
488+// writeJSONRPCError writes a JSON-RPC error response with the given error details.
489+func (s *StreamableHTTPServer) writeJSONRPCError(
490+ w http.ResponseWriter,
491+ id any,
492+ code int,
493+ message string,
494+) {
495+ response := createErrorResponse(id, code, message)
496+ w.Header().Set("Content-Type", "application/json")
497+ w.WriteHeader(http.StatusBadRequest)
498+ err := json.NewEncoder(w).Encode(response)
499+ if err != nil {
500+ s.logger.Errorf("Failed to write JSONRPCError: %v", err)
501+ }
502+}
503+
504+// nextRequestID gets the next incrementing requestID for the current session
505+func (s *StreamableHTTPServer) nextRequestID(sessionID string) int64 {
506+ actual, _ := s.sessionRequestIDs.LoadOrStore(sessionID, new(atomic.Int64))
507+ counter := actual.(*atomic.Int64)
508+ return counter.Add(1)
509+}
510+
511+// --- session ---
512+
513+type sessionToolsStore struct {
514+ mu sync.RWMutex
515+ tools map[string]map[string]ServerTool // sessionID -> toolName -> tool
516+}
517+
518+func newSessionToolsStore() *sessionToolsStore {
519+ return &sessionToolsStore{
520+ tools: make(map[string]map[string]ServerTool),
521+ }
522+}
523+
524+func (s *sessionToolsStore) get(sessionID string) map[string]ServerTool {
525+ s.mu.RLock()
526+ defer s.mu.RUnlock()
527+ return s.tools[sessionID]
528+}
529+
530+func (s *sessionToolsStore) set(sessionID string, tools map[string]ServerTool) {
531+ s.mu.Lock()
532+ defer s.mu.Unlock()
533+ s.tools[sessionID] = tools
534+}
535+
536+func (s *sessionToolsStore) delete(sessionID string) {
537+ s.mu.Lock()
538+ defer s.mu.Unlock()
539+ delete(s.tools, sessionID)
540+}
541+
542+// streamableHttpSession is a session for streamable-http transport
543+// When in POST handlers(request/notification), it's ephemeral, and only exists in the life of the request handler.
544+// When in GET handlers(listening), it's a real session, and will be registered in the MCP server.
545+type streamableHttpSession struct {
546+ sessionID string
547+ notificationChannel chan mcp.JSONRPCNotification // server -> client notifications
548+ tools *sessionToolsStore
549+ upgradeToSSE atomic.Bool
550+}
551+
552+func newStreamableHttpSession(sessionID string, toolStore *sessionToolsStore) *streamableHttpSession {
553+ return &streamableHttpSession{
554+ sessionID: sessionID,
555+ notificationChannel: make(chan mcp.JSONRPCNotification, 100),
556+ tools: toolStore,
557+ }
558+}
559+
560+func (s *streamableHttpSession) SessionID() string {
561+ return s.sessionID
562+}
563+
564+func (s *streamableHttpSession) NotificationChannel() chan<- mcp.JSONRPCNotification {
565+ return s.notificationChannel
566+}
567+
568+func (s *streamableHttpSession) Initialize() {
569+ // do nothing
570+ // the session is ephemeral, no real initialized action needed
571+}
572+
573+func (s *streamableHttpSession) Initialized() bool {
574+ // the session is ephemeral, no real initialized action needed
575+ return true
576+}
577+
578+var _ ClientSession = (*streamableHttpSession)(nil)
579+
580+func (s *streamableHttpSession) GetSessionTools() map[string]ServerTool {
581+ return s.tools.get(s.sessionID)
582+}
583+
584+func (s *streamableHttpSession) SetSessionTools(tools map[string]ServerTool) {
585+ s.tools.set(s.sessionID, tools)
586+}
587+
588+var _ SessionWithTools = (*streamableHttpSession)(nil)
589+
590+func (s *streamableHttpSession) UpgradeToSSEWhenReceiveNotification() {
591+ s.upgradeToSSE.Store(true)
592+}
593+
594+var _ SessionWithStreamableHTTPConfig = (*streamableHttpSession)(nil)
595+
596+// --- session id manager ---
597+
598+type SessionIdManager interface {
599+ Generate() string
600+ // Validate checks if a session ID is valid and not terminated.
601+ // Returns isTerminated=true if the ID is valid but belongs to a terminated session.
602+ // Returns err!=nil if the ID format is invalid or lookup failed.
603+ Validate(sessionID string) (isTerminated bool, err error)
604+ // Terminate marks a session ID as terminated.
605+ // Returns isNotAllowed=true if the server policy prevents client termination.
606+ // Returns err!=nil if the ID is invalid or termination failed.
607+ Terminate(sessionID string) (isNotAllowed bool, err error)
608+}
609+
610+// StatelessSessionIdManager does nothing, which means it has no session management, which is stateless.
611+type StatelessSessionIdManager struct{}
612+
613+func (s *StatelessSessionIdManager) Generate() string {
614+ return ""
615+}
616+func (s *StatelessSessionIdManager) Validate(sessionID string) (isTerminated bool, err error) {
617+ // In stateless mode, ignore session IDs completely - don't validate or reject them
618+ return false, nil
619+}
620+func (s *StatelessSessionIdManager) Terminate(sessionID string) (isNotAllowed bool, err error) {
621+ return false, nil
622+}
623+
624+// InsecureStatefulSessionIdManager generate id with uuid
625+// It won't validate the id indeed, so it could be fake.
626+// For more secure session id, use a more complex generator, like a JWT.
627+type InsecureStatefulSessionIdManager struct{}
628+
629+const idPrefix = "mcp-session-"
630+
631+func (s *InsecureStatefulSessionIdManager) Generate() string {
632+ return idPrefix + uuid.New().String()
633+}
634+func (s *InsecureStatefulSessionIdManager) Validate(sessionID string) (isTerminated bool, err error) {
635+ // validate the session id is a valid uuid
636+ if !strings.HasPrefix(sessionID, idPrefix) {
637+ return false, fmt.Errorf("invalid session id: %s", sessionID)
638+ }
639+ if _, err := uuid.Parse(sessionID[len(idPrefix):]); err != nil {
640+ return false, fmt.Errorf("invalid session id: %s", sessionID)
641+ }
642+ return false, nil
643+}
644+func (s *InsecureStatefulSessionIdManager) Terminate(sessionID string) (isNotAllowed bool, err error) {
645+ return false, nil
646+}
647+
648+// NewTestStreamableHTTPServer creates a test server for testing purposes
649+func NewTestStreamableHTTPServer(server *MCPServer, opts ...StreamableHTTPOption) *httptest.Server {
650+ sseServer := NewStreamableHTTPServer(server, opts...)
651+ testServer := httptest.NewServer(sseServer)
652+ return testServer
653+}
vendor/github.com/mark3labs/mcp-go/util/logger.gonew file+33
@@ -0,0 +1,33 @@
1+package util
2+
3+import (
4+ "log"
5+)
6+
7+// Logger defines a minimal logging interface
8+type Logger interface {
9+ Infof(format string, v ...any)
10+ Errorf(format string, v ...any)
11+}
12+
13+// --- Standard Library Logger Wrapper ---
14+
15+// DefaultStdLogger implements Logger using the standard library's log.Logger.
16+func DefaultLogger() Logger {
17+ return &stdLogger{
18+ logger: log.Default(),
19+ }
20+}
21+
22+// stdLogger wraps the standard library's log.Logger.
23+type stdLogger struct {
24+ logger *log.Logger
25+}
26+
27+func (l *stdLogger) Infof(format string, v ...any) {
28+ l.logger.Printf("INFO: "+format, v...)
29+}
30+
31+func (l *stdLogger) Errorf(format string, v ...any) {
32+ l.logger.Printf("ERROR: "+format, v...)
33+}
vendor/github.com/openai/openai-go/.release-please-manifest.json+1−1
@@ -1,3 +1,3 @@
1{
1{
2− ".": "0.1.0-beta.2"
2+ ".": "1.8.2"
3}
3}
vendor/github.com/openai/openai-go/.stats.yml+4−2
@@ -1,2 +1,4 @@
1−configured_endpoints: 80
1+configured_endpoints: 97
2−openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-5ad6884898c07591750dde560118baf7074a59aecd1f367f930c5e42b04e848a.yml
2+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-a473967d1766dc155994d932fbc4a5bcbd1c140a37c20d0a4065e1bf0640536d.yml
3+openapi_spec_hash: 67cdc62b0d6c8b1de29b7dc54b265749
4+config_hash: 05c7d4a6f4d5983fe9550457114b47dd
vendor/github.com/openai/openai-go/CHANGELOG.md+352
@@ -1,5 +1,357 @@
1# Changelog
1# Changelog
2
2
3+## 1.8.2 (2025-06-27)
4+
5+Full Changelog: [v1.8.1...v1.8.2](https://github.com/openai/openai-go/compare/v1.8.1...v1.8.2)
6+
7+### Bug Fixes
8+
9+* don't try to deserialize as json when ResponseBodyInto is []byte ([74ad0f8](https://github.com/openai/openai-go/commit/74ad0f8fab0f956234503a9ba26fbd395944dcf8))
10+* **pagination:** check if page data is empty in GetNextPage ([c9becdc](https://github.com/openai/openai-go/commit/c9becdc9908f2a1961160837c6ab8cd9064e7854))
11+
12+## 1.8.1 (2025-06-26)
13+
14+Full Changelog: [v1.8.0...v1.8.1](https://github.com/openai/openai-go/compare/v1.8.0...v1.8.1)
15+
16+### Chores
17+
18+* **api:** remove unsupported property ([e22316a](https://github.com/openai/openai-go/commit/e22316adcd8f2c5aa672b12453cbd287de0e1878))
19+* **docs:** update README to include links to docs on Webhooks ([7bb8f85](https://github.com/openai/openai-go/commit/7bb8f8549fdd98997b1d145cbae98ff0146b4e43))
20+
21+## 1.8.0 (2025-06-26)
22+
23+Full Changelog: [v1.7.0...v1.8.0](https://github.com/openai/openai-go/compare/v1.7.0...v1.8.0)
24+
25+### Features
26+
27+* **api:** webhook and deep research support ([f6a7e7d](https://github.com/openai/openai-go/commit/f6a7e7dcd8801facc4f8d981f1ca43786c10de1e))
28+
29+
30+### Chores
31+
32+* **internal:** add tests for breaking change detection ([339522d](https://github.com/openai/openai-go/commit/339522d38cd31b0753a8df37b8924f7e7dfb0b1d))
33+
34+## 1.7.0 (2025-06-23)
35+
36+Full Changelog: [v1.6.0...v1.7.0](https://github.com/openai/openai-go/compare/v1.6.0...v1.7.0)
37+
38+### Features
39+
40+* **api:** make model and inputs not required to create response ([19f0b76](https://github.com/openai/openai-go/commit/19f0b76378d35b3d81c60c85bf2e64d6bf85b9c2))
41+* **api:** update api shapes for usage and code interpreter ([d24d42c](https://github.com/openai/openai-go/commit/d24d42cba60e565627e8ffb1cac63a5085ddb6da))
42+* **client:** add escape hatch for null slice & maps ([9c633d6](https://github.com/openai/openai-go/commit/9c633d6f1dbcc0b153f42f831ee7e13d6fe62296))
43+
44+
45+### Chores
46+
47+* fix documentation of null map ([8f3a134](https://github.com/openai/openai-go/commit/8f3a134e500b1b7791ab855adaef2d7b10d2d1c3))
48+
49+## 1.6.0 (2025-06-17)
50+
51+Full Changelog: [v1.5.0...v1.6.0](https://github.com/openai/openai-go/compare/v1.5.0...v1.6.0)
52+
53+### Features
54+
55+* **api:** add reusable prompt IDs ([280c698](https://github.com/openai/openai-go/commit/280c698015eba5f6bd47e2fce038eb401f6ef0f2))
56+* **api:** manual updates ([740f840](https://github.com/openai/openai-go/commit/740f84006ac283a25f5ad96aaf845a3c8a51c6ac))
57+* **client:** add debug log helper ([5715c49](https://github.com/openai/openai-go/commit/5715c491c483f8dab4ea2a900c400384f6810024))
58+
59+
60+### Chores
61+
62+* **ci:** enable for pull requests ([9ed793a](https://github.com/openai/openai-go/commit/9ed793a51010423db464a7b7bd263d2fd275967f))
63+
64+## 1.5.0 (2025-06-10)
65+
66+Full Changelog: [v1.4.0...v1.5.0](https://github.com/openai/openai-go/compare/v1.4.0...v1.5.0)
67+
68+### Features
69+
70+* **api:** Add o3-pro model IDs ([3bbd0b8](https://github.com/openai/openai-go/commit/3bbd0b8f09030a6c571900d444742c4fc2a3c211))
71+
72+## 1.4.0 (2025-06-09)
73+
74+Full Changelog: [v1.3.0...v1.4.0](https://github.com/openai/openai-go/compare/v1.3.0...v1.4.0)
75+
76+### Features
77+
78+* **client:** allow overriding unions ([27c6299](https://github.com/openai/openai-go/commit/27c6299cb4ac275c6542b5691d81b795e65eeff6))
79+
80+
81+### Bug Fixes
82+
83+* **client:** cast to raw message when converting to params ([a3282b0](https://github.com/openai/openai-go/commit/a3282b01a8d9a2c0cd04f24b298bf2ffcd160ebd))
84+
85+## 1.3.0 (2025-06-03)
86+
87+Full Changelog: [v1.2.1...v1.3.0](https://github.com/openai/openai-go/compare/v1.2.1...v1.3.0)
88+
89+### Features
90+
91+* **api:** add new realtime and audio models, realtime session options ([8b8f62b](https://github.com/openai/openai-go/commit/8b8f62b8e185f3fe4aaa99e892df5d35638931a1))
92+
93+## 1.2.1 (2025-06-02)
94+
95+Full Changelog: [v1.2.0...v1.2.1](https://github.com/openai/openai-go/compare/v1.2.0...v1.2.1)
96+
97+### Bug Fixes
98+
99+* **api:** Fix evals and code interpreter interfaces ([7e244c7](https://github.com/openai/openai-go/commit/7e244c73caad6b4768cced9a798452f03b1165c8))
100+* fix error ([a200fca](https://github.com/openai/openai-go/commit/a200fca92c3fa413cf724f424077d1537fa2ca3e))
101+
102+
103+### Chores
104+
105+* make go mod tidy continue on error ([48f41c2](https://github.com/openai/openai-go/commit/48f41c2993bf6181018da859ae759951261f9ee2))
106+
107+## 1.2.0 (2025-05-29)
108+
109+Full Changelog: [v1.1.0...v1.2.0](https://github.com/openai/openai-go/compare/v1.1.0...v1.2.0)
110+
111+### Features
112+
113+* **api:** Config update for pakrym-stream-param ([84d59d5](https://github.com/openai/openai-go/commit/84d59d5cbc7521ddcc04435317903fd4ec3d17f6))
114+
115+
116+### Bug Fixes
117+
118+* **client:** return binary content from `get /containers/{container_id}/files/{file_id}/content` ([f8c8de1](https://github.com/openai/openai-go/commit/f8c8de18b720b224267d54da53d7d919ed0fdff3))
119+
120+
121+### Chores
122+
123+* deprecate Assistants API ([027470e](https://github.com/openai/openai-go/commit/027470e066ea6bbca1aeeb4fb9a8a3430babb84c))
124+* **internal:** fix release workflows ([fd46533](https://github.com/openai/openai-go/commit/fd4653316312755ccab7435fca9fb0a2d8bf8fbb))
125+
126+## 1.1.0 (2025-05-22)
127+
128+Full Changelog: [v1.0.0...v1.1.0](https://github.com/openai/openai-go/compare/v1.0.0...v1.1.0)
129+
130+### Features
131+
132+* **api:** add container endpoint ([2bd777d](https://github.com/openai/openai-go/commit/2bd777d6813b5dfcd3a2d339047a944c478dcd64))
133+* **api:** new API tools ([e7e2123](https://github.com/openai/openai-go/commit/e7e2123de7cafef515e07adde6edd45a7035b610))
134+* **api:** new streaming helpers for background responses ([422a0db](https://github.com/openai/openai-go/commit/422a0db3c674135e23dd200f5d8d785bd0be33e6))
135+
136+
137+### Chores
138+
139+* **docs:** grammar improvements ([f4b23dd](https://github.com/openai/openai-go/commit/f4b23dd31facfc8839310854521b48060ef76be2))
140+* improve devcontainer setup ([dfdaeec](https://github.com/openai/openai-go/commit/dfdaeec2d6dd5cd679514d60c49b68c5df9e1b1e))
141+
142+## 1.0.0 (2025-05-19)
143+
144+Full Changelog: [v0.1.0-beta.11...v1.0.0](https://github.com/openai/openai-go/compare/v0.1.0-beta.11...v1.0.0)
145+
146+### ⚠ BREAKING CHANGES
147+
148+* **client:** rename file array param variant
149+* **api:** improve naming and remove assistants
150+* **accumulator:** update casing ([#401](https://github.com/openai/openai-go/issues/401))
151+
152+### Features
153+
154+* **api:** improve naming and remove assistants ([4c623b8](https://github.com/openai/openai-go/commit/4c623b88a9025db1961cc57985eb7374342f43e7))
155+
156+
157+### Bug Fixes
158+
159+* **accumulator:** update casing ([#401](https://github.com/openai/openai-go/issues/401)) ([d59453c](https://github.com/openai/openai-go/commit/d59453c95b89fdd0b51305778dec0a39ce3a9d2a))
160+* **client:** correctly set stream key for multipart ([0ec68f0](https://github.com/openai/openai-go/commit/0ec68f0d779e7726931b1115eca9ae81eab59ba8))
161+* **client:** don't panic on marshal with extra null field ([9c15332](https://github.com/openai/openai-go/commit/9c153320272d212beaa516d4c70d54ae8053a958))
162+* **client:** increase max stream buffer size ([9456455](https://github.com/openai/openai-go/commit/945645559c5d68d9e28cf445d9c3b83e5fc6bd35))
163+* **client:** rename file array param variant ([4cfcf86](https://github.com/openai/openai-go/commit/4cfcf869280e7531fbbc8c00db0dd9271d07c423))
164+* **client:** use scanner for streaming ([aa58806](https://github.com/openai/openai-go/commit/aa58806bffc3aed68425c480414ddbb4dac3fa78))
165+
166+
167+### Chores
168+
169+* **docs:** typo fix ([#400](https://github.com/openai/openai-go/issues/400)) ([bececf2](https://github.com/openai/openai-go/commit/bececf24cd0324b7c991b7d7f1d3eff6bf71f996))
170+* **examples:** migrate enum ([#447](https://github.com/openai/openai-go/issues/447)) ([814dd8b](https://github.com/openai/openai-go/commit/814dd8b6cfe4eeb535dc8ecd161a409ea2eb6698))
171+* **examples:** migrate to latest version ([#444](https://github.com/openai/openai-go/issues/444)) ([1c8754f](https://github.com/openai/openai-go/commit/1c8754ff905ed023f6381c8493910d63039407de))
172+* **examples:** remove beta assisstants examples ([#445](https://github.com/openai/openai-go/issues/445)) ([5891583](https://github.com/openai/openai-go/commit/589158372be9c0517b5508f9ccd872fdb1fe480b))
173+* **example:** update fine-tuning ([#450](https://github.com/openai/openai-go/issues/450)) ([421e3c5](https://github.com/openai/openai-go/commit/421e3c5065ace2d5ddd3d13a036477fff9123e5f))
174+
175+## 0.1.0-beta.11 (2025-05-16)
176+
177+Full Changelog: [v0.1.0-beta.10...v0.1.0-beta.11](https://github.com/openai/openai-go/compare/v0.1.0-beta.10...v0.1.0-beta.11)
178+
179+### ⚠ BREAKING CHANGES
180+
181+* **client:** clearer array variant names
182+* **client:** rename resp package
183+* **client:** improve core function names
184+* **client:** improve union variant names
185+* **client:** improve param subunions & deduplicate types
186+
187+### Features
188+
189+* **api:** add image sizes, reasoning encryption ([0852fb3](https://github.com/openai/openai-go/commit/0852fb3101dc940761f9e4f32875bfcf3669eada))
190+* **api:** add o3 and o4-mini model IDs ([3fabca6](https://github.com/openai/openai-go/commit/3fabca6b5c610edfb7bcd0cab5334a06444df0b0))
191+* **api:** Add reinforcement fine-tuning api support ([831a124](https://github.com/openai/openai-go/commit/831a12451cfce907b5ae4d294b9c2ac95f40d97a))
192+* **api:** adding gpt-4.1 family of model IDs ([1ef19d4](https://github.com/openai/openai-go/commit/1ef19d4cc94992dc435d7d5f28b30c9b1d255cd4))
193+* **api:** adding new image model support ([bf17880](https://github.com/openai/openai-go/commit/bf17880e182549c5c0fc34ec05df3184f223bc00))
194+* **api:** manual updates ([11f5716](https://github.com/openai/openai-go/commit/11f5716afa86aa100f80f3fa127e1d49203e5e21))
195+* **api:** responses x eval api ([183aaf7](https://github.com/openai/openai-go/commit/183aaf700f1d7ffad4ac847627d9ace65379c459))
196+* **api:** Updating Assistants and Evals API schemas ([47ca619](https://github.com/openai/openai-go/commit/47ca619fa1b439cf3a68c98e48e9bf1942f0568b))
197+* **client:** add dynamic streaming buffer to handle large lines ([8e6aad6](https://github.com/openai/openai-go/commit/8e6aad6d54fc73f1fcc174e1f06c9b3cf00c2689))
198+* **client:** add helper method to generate constant structs ([ff82809](https://github.com/openai/openai-go/commit/ff828094b561fc11184fed83f04424b6f68f7781))
199+* **client:** add support for endpoint-specific base URLs in python ([072dce4](https://github.com/openai/openai-go/commit/072dce46486d373fa0f0de5415f5270b01c2d972))
200+* **client:** add support for reading base URL from environment variable ([0d37268](https://github.com/openai/openai-go/commit/0d372687d673990290bad583f1906a2b121960b2))
201+* **client:** clearer array variant names ([a5d8b5d](https://github.com/openai/openai-go/commit/a5d8b5d6b161e3083184586840b2cbe0606d8de1))
202+* **client:** experimental support for unmarshalling into param structs ([5234875](https://github.com/openai/openai-go/commit/523487582e15a47e2f409f183568551258f4b8fe))
203+* **client:** improve param subunions & deduplicate types ([8a78f37](https://github.com/openai/openai-go/commit/8a78f37c25abf10498d16d210de3078f491ff23e))
204+* **client:** rename resp package ([4433516](https://github.com/openai/openai-go/commit/443351625ee290937a25425719b099ce785bd21b))
205+* **client:** support more time formats ([ec171b2](https://github.com/openai/openai-go/commit/ec171b2405c46f9cf04560760da001f7133d2fec))
206+* fix lint ([9c50a1e](https://github.com/openai/openai-go/commit/9c50a1eb9f93b578cb78085616f6bfab69f21dbc))
207+
208+
209+### Bug Fixes
210+
211+* **client:** clean up reader resources ([710b92e](https://github.com/openai/openai-go/commit/710b92eaa7e94c03aeeca7479668677b32acb154))
212+* **client:** correctly update body in WithJSONSet ([f2d7118](https://github.com/openai/openai-go/commit/f2d7118295dd3073aa449426801d02e6f60bdaa3))
213+* **client:** improve core function names ([9f312a9](https://github.com/openai/openai-go/commit/9f312a9b14f5424d44d5834f1b82f3d3fcd57db2))
214+* **client:** improve union variant names ([a2c3de9](https://github.com/openai/openai-go/commit/a2c3de9e6c9f6e406b953f6de2eb78d1e72ec1b5))
215+* **client:** include path for type names in example code ([69561c5](https://github.com/openai/openai-go/commit/69561c549e18bd16a3641d62769479b125a4e955))
216+* **client:** resolve issue with optional multipart files ([910d173](https://github.com/openai/openai-go/commit/910d1730e97a03898e5dee7c889844a2ccec3e56))
217+* **client:** time format encoding fix ([ca17553](https://github.com/openai/openai-go/commit/ca175533ac8a17d36be1f531bbaa89c770da3f58))
218+* **client:** unmarshal responses properly ([fc9fec3](https://github.com/openai/openai-go/commit/fc9fec3c466ba9f633c3f7a4eebb5ebd3b85e8ac))
219+* handle empty bodies in WithJSONSet ([8372464](https://github.com/openai/openai-go/commit/83724640c6c00dcef1547dcabace309f17d14afc))
220+* **pagination:** handle errors when applying options ([eebf84b](https://github.com/openai/openai-go/commit/eebf84bf19f0eb6d9fa21e64bb83b0258e8cb42c))
221+
222+
223+### Chores
224+
225+* **ci:** add timeout thresholds for CI jobs ([26b0dd7](https://github.com/openai/openai-go/commit/26b0dd760c142ca3aa287e8441bbe44cc8b3be0b))
226+* **ci:** only use depot for staging repos ([7682154](https://github.com/openai/openai-go/commit/7682154fdbcbe2a2ffdb2df590647a1712d52275))
227+* **ci:** run on more branches and use depot runners ([d7badbc](https://github.com/openai/openai-go/commit/d7badbc0d17bcf3cffec332f65cb68e531cb3176))
228+* **docs:** document pre-request options ([4befa5a](https://github.com/openai/openai-go/commit/4befa5a48ca61372715f36c45e72eb159d95bf2d))
229+* **docs:** update respjson package name ([9a00229](https://github.com/openai/openai-go/commit/9a002299a91e1145f053c51b1a4de10298fd2f43))
230+* **readme:** improve formatting ([a847e8d](https://github.com/openai/openai-go/commit/a847e8df45f725f9652fcea53ce57d3b9046efc7))
231+* **utils:** add internal resp to param utility ([239c4e2](https://github.com/openai/openai-go/commit/239c4e2cb32c7af71ab14668ccc2f52ea59653f9))
232+
233+
234+### Documentation
235+
236+* update documentation links to be more uniform ([f5f0bb0](https://github.com/openai/openai-go/commit/f5f0bb05ee705d84119806f8e703bf2e0becb1fa))
237+
238+## 0.1.0-beta.10 (2025-04-14)
239+
240+Full Changelog: [v0.1.0-beta.9...v0.1.0-beta.10](https://github.com/openai/openai-go/compare/v0.1.0-beta.9...v0.1.0-beta.10)
241+
242+### Chores
243+
244+* **internal:** expand CI branch coverage ([#369](https://github.com/openai/openai-go/issues/369)) ([258dda8](https://github.com/openai/openai-go/commit/258dda8007a69b9c2720b225ee6d27474d676a93))
245+* **internal:** reduce CI branch coverage ([a2f7c03](https://github.com/openai/openai-go/commit/a2f7c03eb984d98f29f908df103ea1743f2e3d9a))
246+
247+## 0.1.0-beta.9 (2025-04-09)
248+
249+Full Changelog: [v0.1.0-beta.8...v0.1.0-beta.9](https://github.com/openai/openai-go/compare/v0.1.0-beta.8...v0.1.0-beta.9)
250+
251+### Chores
252+
253+* workaround build errors ([#366](https://github.com/openai/openai-go/issues/366)) ([adeb003](https://github.com/openai/openai-go/commit/adeb003cab8efbfbf4424e03e96a0f5e728551cb))
254+
255+## 0.1.0-beta.8 (2025-04-09)
256+
257+Full Changelog: [v0.1.0-beta.7...v0.1.0-beta.8](https://github.com/openai/openai-go/compare/v0.1.0-beta.7...v0.1.0-beta.8)
258+
259+### Features
260+
261+* **api:** Add evalapi to sdk ([#360](https://github.com/openai/openai-go/issues/360)) ([88977d1](https://github.com/openai/openai-go/commit/88977d1868dbbe0060c56ba5dac8eb19773e4938))
262+* **api:** manual updates ([#363](https://github.com/openai/openai-go/issues/363)) ([5d068e0](https://github.com/openai/openai-go/commit/5d068e0053172db7f5b75038aa215eee074eeeed))
263+* **client:** add escape hatch to omit required param fields ([#354](https://github.com/openai/openai-go/issues/354)) ([9690d6b](https://github.com/openai/openai-go/commit/9690d6b49f8b00329afc038ec15116750853e620))
264+* **client:** support custom http clients ([#357](https://github.com/openai/openai-go/issues/357)) ([b5a624f](https://github.com/openai/openai-go/commit/b5a624f658cad774094427b36b05e446b41e8c52))
265+
266+
267+### Chores
268+
269+* **docs:** readme improvements ([#356](https://github.com/openai/openai-go/issues/356)) ([b2f8539](https://github.com/openai/openai-go/commit/b2f8539d6316e3443aa733be2c95926696119c13))
270+* **internal:** fix examples ([#361](https://github.com/openai/openai-go/issues/361)) ([de398b4](https://github.com/openai/openai-go/commit/de398b453d398299eb80c15f8fdb2bcbef5eeed6))
271+* **internal:** skip broken test ([#362](https://github.com/openai/openai-go/issues/362)) ([cccead9](https://github.com/openai/openai-go/commit/cccead9ba916142ac8fbe6e8926d706511e32ae3))
272+* **tests:** improve enum examples ([#359](https://github.com/openai/openai-go/issues/359)) ([e0b9739](https://github.com/openai/openai-go/commit/e0b9739920114d6e991d3947b67fdf62cfaa09c7))
273+
274+## 0.1.0-beta.7 (2025-04-07)
275+
276+Full Changelog: [v0.1.0-beta.6...v0.1.0-beta.7](https://github.com/openai/openai-go/compare/v0.1.0-beta.6...v0.1.0-beta.7)
277+
278+### Features
279+
280+* **client:** make response union's AsAny method type safe ([#352](https://github.com/openai/openai-go/issues/352)) ([1252f56](https://github.com/openai/openai-go/commit/1252f56c917e57d6d2b031501b2ff5f89f87cf87))
281+
282+
283+### Chores
284+
285+* **docs:** doc improvements ([#350](https://github.com/openai/openai-go/issues/350)) ([80debc8](https://github.com/openai/openai-go/commit/80debc824eaacb4b07c8f3e8b1d0488d860d5be5))
286+
287+## 0.1.0-beta.6 (2025-04-04)
288+
289+Full Changelog: [v0.1.0-beta.5...v0.1.0-beta.6](https://github.com/openai/openai-go/compare/v0.1.0-beta.5...v0.1.0-beta.6)
290+
291+### Features
292+
293+* **api:** manual updates ([4e39609](https://github.com/openai/openai-go/commit/4e39609d499b88039f1c90cc4b56e26f28fd58ea))
294+* **client:** support unions in query and forms ([#347](https://github.com/openai/openai-go/issues/347)) ([cf8af37](https://github.com/openai/openai-go/commit/cf8af373ab7c019c75e886855009ffaca320d0e3))
295+
296+## 0.1.0-beta.5 (2025-04-03)
297+
298+Full Changelog: [v0.1.0-beta.4...v0.1.0-beta.5](https://github.com/openai/openai-go/compare/v0.1.0-beta.4...v0.1.0-beta.5)
299+
300+### Features
301+
302+* **api:** manual updates ([563cc50](https://github.com/openai/openai-go/commit/563cc505f2ab17749bb77e937342a6614243b975))
303+* **client:** omitzero on required id parameter ([#339](https://github.com/openai/openai-go/issues/339)) ([c0b4842](https://github.com/openai/openai-go/commit/c0b484266ccd9faee66873916d8c0c92ea9f1014))
304+
305+
306+### Bug Fixes
307+
308+* **client:** return error on bad custom url instead of panic ([#341](https://github.com/openai/openai-go/issues/341)) ([a06c5e6](https://github.com/openai/openai-go/commit/a06c5e632242e53d3fdcc8964931acb533a30b7e))
309+* **client:** support multipart encoding array formats ([#342](https://github.com/openai/openai-go/issues/342)) ([5993b28](https://github.com/openai/openai-go/commit/5993b28309d02c2d748b54d98934ef401dcd193a))
310+* **client:** unmarshal stream events into fresh memory ([#340](https://github.com/openai/openai-go/issues/340)) ([52c3e08](https://github.com/openai/openai-go/commit/52c3e08f51d471d728e5acd16b3c304b51be2d03))
311+
312+## 0.1.0-beta.4 (2025-04-02)
313+
314+Full Changelog: [v0.1.0-beta.3...v0.1.0-beta.4](https://github.com/openai/openai-go/compare/v0.1.0-beta.3...v0.1.0-beta.4)
315+
316+### Features
317+
318+* **api:** manual updates ([bc4fe73](https://github.com/openai/openai-go/commit/bc4fe73eec9c4d39229e4beae8eaafb55b1d3364))
319+* **api:** manual updates ([aa7ff10](https://github.com/openai/openai-go/commit/aa7ff10b0616a6b2ece45cb10e9c83f25e35aded))
320+
321+
322+### Chores
323+
324+* **docs:** update file uploads in README ([#333](https://github.com/openai/openai-go/issues/333)) ([471c452](https://github.com/openai/openai-go/commit/471c4525c94e83cf4b78cb6c9b2f65a8a27bf3ce))
325+* **internal:** codegen related update ([#335](https://github.com/openai/openai-go/issues/335)) ([48422dc](https://github.com/openai/openai-go/commit/48422dcca333ab808ccb02506c033f1c69d2aa19))
326+* Remove deprecated/unused remote spec feature ([c5077a1](https://github.com/openai/openai-go/commit/c5077a154a6db79b73cf4978bdc08212c6da6423))
327+
328+## 0.1.0-beta.3 (2025-03-28)
329+
330+Full Changelog: [v0.1.0-beta.2...v0.1.0-beta.3](https://github.com/openai/openai-go/compare/v0.1.0-beta.2...v0.1.0-beta.3)
331+
332+### ⚠ BREAKING CHANGES
333+
334+* **client:** add enums ([#327](https://github.com/openai/openai-go/issues/327))
335+
336+### Features
337+
338+* **api:** add `get /chat/completions` endpoint ([e8ed116](https://github.com/openai/openai-go/commit/e8ed1168576c885cb26fbf819b9c8d24975749bd))
339+* **api:** add `get /responses/{response_id}/input_items` endpoint ([8870c26](https://github.com/openai/openai-go/commit/8870c26f010a596adcf37ac10dba096bdd4394e3))
340+
341+
342+### Bug Fixes
343+
344+* **client:** add enums ([#327](https://github.com/openai/openai-go/issues/327)) ([b0e3afb](https://github.com/openai/openai-go/commit/b0e3afbd6f18fd9fc2a5ea9174bd7ec0ac0614db))
345+
346+
347+### Chores
348+
349+* add hash of OpenAPI spec/config inputs to .stats.yml ([104b786](https://github.com/openai/openai-go/commit/104b7861bb025514999b143f7d1de45d2dab659f))
350+* add request options to client tests ([#321](https://github.com/openai/openai-go/issues/321)) ([f5239ce](https://github.com/openai/openai-go/commit/f5239ceecf36835341eac5121ed1770020c4806a))
351+* **api:** updates to supported Voice IDs ([#325](https://github.com/openai/openai-go/issues/325)) ([477727a](https://github.com/openai/openai-go/commit/477727a44b0fb72493c4749cc60171e0d30f98ec))
352+* **docs:** improve security documentation ([#319](https://github.com/openai/openai-go/issues/319)) ([0271053](https://github.com/openai/openai-go/commit/027105363ab30ac3e189234908169faf94e0ca49))
353+* fix typos ([#324](https://github.com/openai/openai-go/issues/324)) ([dba15f7](https://github.com/openai/openai-go/commit/dba15f74d63814ce16f778e1017a209a42f46179))
354+
3## 0.1.0-beta.2 (2025-03-22)
355## 0.1.0-beta.2 (2025-03-22)
4
356
5Full Changelog: [v0.1.0-beta.1...v0.1.0-beta.2](https://github.com/openai/openai-go/compare/v0.1.0-beta.1...v0.1.0-beta.2)
357Full Changelog: [v0.1.0-beta.1...v0.1.0-beta.2](https://github.com/openai/openai-go/compare/v0.1.0-beta.1...v0.1.0-beta.2)
vendor/github.com/openai/openai-go/CONTRIBUTING.md+1−1
@@ -4,7 +4,7 @@ To set up the repository, run:
4
4
5```sh
5```sh
6$ ./scripts/bootstrap
6$ ./scripts/bootstrap
7−$ ./scripts/build
7+$ ./scripts/lint
8```
8```
9
9
10This will install all the required dependencies and build the SDK.
10This will install all the required dependencies and build the SDK.
vendor/github.com/openai/openai-go/MIGRATION.md+14−14
@@ -227,15 +227,15 @@ var name *string = animal.GetName()
227
227
228The old SDK had a function `param.Null[T]()` which could set `param.Field[T]` to `null`.
228The old SDK had a function `param.Null[T]()` which could set `param.Field[T]` to `null`.
229
229
230−The new SDK uses `param.NullOpt[T]()` for to set a `param.Opt[T]` to `null`,
230+The new SDK uses `param.Null[T]()` for to set a `param.Opt[T]` to `null`,
231−and `param.NullObj[T]()` to set a param struct `T` to `null`.
231+but `param.NullStruct[T]()` to set a param struct `T` to `null`.
232
232
233```diff
233```diff
234−- var nullObj param.Field[BarParam] = param.Null[BarParam]()
235−+ var nullObj BarParam = param.NullObj[BarParam]()
236−
237- var nullPrimitive param.Field[int64] = param.Null[int64]()
234- var nullPrimitive param.Field[int64] = param.Null[int64]()
238−+ var nullPrimitive param.Opt[int64] = param.NullOpt[int64]()
235++ var nullPrimitive param.Opt[int64] = param.Null[int64]()
236+
237+- var nullStruct param.Field[BarParam] = param.Null[BarParam]()
238++ var nullStruct BarParam = param.NullStruct[BarParam]()
239```
239```
240
240
241## Sending custom values
241## Sending custom values
@@ -248,7 +248,7 @@ foo := FooParams{
248 A: param.String("hello"),
248 A: param.String("hello"),
249- B: param.Raw[string](12) // sending `12` instead of a string
249- B: param.Raw[string](12) // sending `12` instead of a string
250}
250}
251−+ foo.WithExtraFields(map[string]any{
251++ foo.SetExtraFields(map[string]any{
252+ "B": 12,
252+ "B": 12,
253+ })
253+ })
254```
254```
@@ -257,20 +257,20 @@ foo := FooParams{
257
257
258## Checking for presence of optional fields
258## Checking for presence of optional fields
259
259
260−The `.IsNull()` method has been changed to `.IsPresent()` to better reflect its behavior.
260+The `.IsNull()` method has been changed to `.Valid()` to better reflect its behavior.
261
261
262```diff
262```diff
263- if !resp.Foo.JSON.Bar.IsNull() {
263- if !resp.Foo.JSON.Bar.IsNull() {
264−+ if resp.Foo.JSON.Bar.IsPresent() {
264++ if resp.Foo.JSON.Bar.Valid() {
265 println("bar is present:", resp.Foo.Bar)
265 println("bar is present:", resp.Foo.Bar)
266}
266}
267```
267```
268
268
269−| Previous | New | Returns true for values |
269+| Previous | New | Returns true for values |
270−| -------------- | ------------------- | ----------------------- |
270+| -------------- | ------------------------ | ----------------------- |
271−| `.IsNull()` | `!.IsPresent()` | `null` or Omitted |
271+| `.IsNull()` | `!.Valid()` | `null` or Omitted |
272−| `.IsMissing()` | `.Raw() == ""` | Omitted |
272+| `.IsMissing()` | `.Raw() == resp.Omitted` | Omitted |
273−| | `.IsExplicitNull()` | `null` |
273+| | `.Raw() == resp.Null` |
274
274
275## Checking Raw JSON of a response
275## Checking Raw JSON of a response
276
276
vendor/github.com/openai/openai-go/README.md+219−79
@@ -2,8 +2,8 @@
2
2
3<a href="https://pkg.go.dev/github.com/openai/openai-go"><img src="https://pkg.go.dev/badge/github.com/openai/openai-go.svg" alt="Go Reference"></a>
3<a href="https://pkg.go.dev/github.com/openai/openai-go"><img src="https://pkg.go.dev/badge/github.com/openai/openai-go.svg" alt="Go Reference"></a>
4
4
5−The OpenAI Go library provides convenient access to [the OpenAI REST
5+The OpenAI Go library provides convenient access to the [OpenAI REST API](https://platform.openai.com/docs)
6−API](https://platform.openai.com/docs) from applications written in Go. The full API of this library can be found in [api.md](api.md).
6+from applications written in Go.
7
7
8> [!WARNING]
8> [!WARNING]
9> The latest version of this package uses a new design with significant breaking changes.
9> The latest version of this package uses a new design with significant breaking changes.
@@ -26,7 +26,7 @@ Or to pin the version:
26<!-- x-release-please-start-version -->
26<!-- x-release-please-start-version -->
27
27
28```sh
28```sh
29−go get -u 'github.com/openai/openai-go@v0.1.0-beta.2'
29+go get -u 'github.com/openai/openai-go@v1.8.2'
30```
30```
31
31
32<!-- x-release-please-end -->
32<!-- x-release-please-end -->
@@ -295,52 +295,59 @@ func main() {
295The openai library uses the [`omitzero`](https://tip.golang.org/doc/go1.24#encodingjsonpkgencodingjson)
295The openai library uses the [`omitzero`](https://tip.golang.org/doc/go1.24#encodingjsonpkgencodingjson)
296semantics from the Go 1.24+ `encoding/json` release for request fields.
296semantics from the Go 1.24+ `encoding/json` release for request fields.
297
297
298−Required primitive fields (`int64`, `string`, etc.) feature the tag <code>\`json:...,required\`</code>. These
298+Required primitive fields (`int64`, `string`, etc.) feature the tag <code>\`json:"...,required"\`</code>. These
299fields are always serialized, even their zero values.
299fields are always serialized, even their zero values.
300
300
301−Optional primitive types are wrapped in a `param.Opt[T]`. Use the provided constructors set `param.Opt[T]` fields such as `openai.String(string)`, `openai.Int(int64)`, etc.
301+Optional primitive types are wrapped in a `param.Opt[T]`. These fields can be set with the provided constructors, `openai.String(string)`, `openai.Int(int64)`, etc.
302
302
303−Optional primitives, maps, slices and structs and string enums (represented as `string`) always feature the
303+Any `param.Opt[T]`, map, slice, struct or string enum uses the
304−tag <code>\`json:"...,omitzero"\`</code>. Their zero values are considered omitted.
304+tag <code>\`json:"...,omitzero"\`</code>. Its zero value is considered omitted.
305
305
306−Any non-nil slice of length zero will serialize as an empty JSON array, `"[]"`. Similarly, any non-nil map with length zero with serialize as an empty JSON object, `"{}"`.
306+The `param.IsOmitted(any)` function can confirm the presence of any `omitzero` field.
307−
308−To send `null` instead of an `param.Opt[T]`, use `param.NullOpt[T]()`.
309−To send `null` instead of a struct, use `param.NullObj[T]()`, where `T` is a struct.
310−To send a custom value instead of a struct, use `param.OverrideObj[T](value)`.
311−
312−To override request structs contain a `.WithExtraFields(map[string]any)` method which can be used to
313−send non-conforming fields in the request body. Extra fields take higher precedence than normal
314−fields.
315
307
316```go
308```go
317−params := FooParams{
309+p := openai.ExampleParams{
318− ID: "id_xxx", // required property
310+ ID: "id_xxx", // required property
319− Name: openai.String("hello"), // optional property
311+ Name: openai.String("..."), // optional property
320− Description: param.NullOpt[string](), // explicit null property
321
312
322 Point: openai.Point{
313 Point: openai.Point{
323− X: 0, // required field will serialize as 0
314+ X: 0, // required field will serialize as 0
324 Y: openai.Int(1), // optional field will serialize as 1
315 Y: openai.Int(1), // optional field will serialize as 1
325− // ... omitted non-required fields will not be serialized
316+ // ... omitted non-required fields will not be serialized
326− }),
317+ },
327
318
328 Origin: openai.Origin{}, // the zero value of [Origin] is considered omitted
319 Origin: openai.Origin{}, // the zero value of [Origin] is considered omitted
329}
320}
321+```
322+
323+To send `null` instead of a `param.Opt[T]`, use `param.Null[T]()`.
324+To send `null` instead of a struct `T`, use `param.NullStruct[T]()`.
325+
326+```go
327+p.Name = param.Null[string]() // 'null' instead of string
328+p.Point = param.NullStruct[Point]() // 'null' instead of struct
329+
330+param.IsNull(p.Name) // true
331+param.IsNull(p.Point) // true
332+```
330
333
334+Request structs contain a `.SetExtraFields(map[string]any)` method which can send non-conforming
335+fields in the request body. Extra fields overwrite any struct fields with a matching
336+key. For security reasons, only use `SetExtraFields` with trusted data.
337+
338+To send a custom value instead of a struct, use `param.Override[T](value)`.
339+
340+```go
331// In cases where the API specifies a given type,
341// In cases where the API specifies a given type,
332−// but you want to send something else, use [WithExtraFields]:
342+// but you want to send something else, use [SetExtraFields]:
333−params.WithExtraFields(map[string]any{
343+p.SetExtraFields(map[string]any{
334 "x": 0.01, // send "x" as a float instead of int
344 "x": 0.01, // send "x" as a float instead of int
335})
345})
336
346
337// Send a number instead of an object
347// Send a number instead of an object
338−custom := param.OverrideObj[openai.FooParams](12)
348+custom := param.Override[openai.FooParams](12)
339```
349```
340
350
341−When available, use the `.IsPresent()` method to check if an optional parameter is not omitted or `null`.
342−Otherwise, the `param.IsOmitted(any)` function can confirm the presence of any `omitzero` field.
343−
344### Request unions
351### Request unions
345
352
346Unions are represented as a struct with fields prefixed by "Of" for each of it's variants,
353Unions are represented as a struct with fields prefixed by "Of" for each of it's variants,
@@ -352,8 +359,8 @@ These methods return a mutable pointer to the underlying data, if present.
352```go
359```go
353// Only one field can be non-zero, use param.IsOmitted() to check if a field is set
360// Only one field can be non-zero, use param.IsOmitted() to check if a field is set
354type AnimalUnionParam struct {
361type AnimalUnionParam struct {
355− OfCat *Cat `json:",omitzero,inline`
362+ OfCat *Cat `json:",omitzero,inline`
356− OfDog *Dog `json:",omitzero,inline`
363+ OfDog *Dog `json:",omitzero,inline`
357}
364}
358
365
359animal := AnimalUnionParam{
366animal := AnimalUnionParam{
@@ -373,34 +380,54 @@ if address := animal.GetOwner().GetAddress(); address != nil {
373
380
374### Response objects
381### Response objects
375
382
376−All fields in response structs are value types (not pointers or wrappers).
383+All fields in response structs are ordinary value types (not pointers or wrappers).
384+Response structs also include a special `JSON` field containing metadata about
385+each property.
386+
387+```go
388+type Animal struct {
389+ Name string `json:"name,nullable"`
390+ Owners int `json:"owners"`
391+ Age int `json:"age"`
392+ JSON struct {
393+ Name respjson.Field
394+ Owner respjson.Field
395+ Age respjson.Field
396+ ExtraFields map[string]respjson.Field
397+ } `json:"-"`
398+}
399+```
377
400
378−If a given field is `null`, not present, or invalid, the corresponding field
401+To handle optional data, use the `.Valid()` method on the JSON field.
379−will simply be its zero value.
402+`.Valid()` returns true if a field is not `null`, not present, or couldn't be marshaled.
380
403
381−All response structs also include a special `JSON` field, containing more detailed
404+If `.Valid()` is false, the corresponding field will simply be its zero value.
382−information about each property, which you can use like so:
383
405
384```go
406```go
385−if res.Name == "" {
407+raw := `{"owners": 1, "name": null}`
386− // true if `"name"` was unmarshalled successfully
408+
387− res.JSON.Name.IsPresent()
409+var res Animal
388−
389− res.JSON.Name.IsExplicitNull() // true if `"name"` is explicitly null
390− res.JSON.Name.Raw() == "" // true if `"name"` field does not exist
391−
392− // When the API returns data that cannot be coerced to the expected type:
393− if !res.JSON.Name.IsPresent() && res.JSON.Name.Raw() != "" {
394− raw := res.JSON.Name.Raw()
395−
396− legacyName := struct{
397− First string `json:"first"`
398− Last string `json:"last"`
399− }{}
400− json.Unmarshal([]byte(raw), &legacyName)
410+json.Unmarshal([]byte(raw), &res)
401− name = legacyName.First + " " + legacyName.Last
411+
402− }
412+// Accessing regular fields
403−}
413+
414+res.Owners // 1
415+res.Name // ""
416+res.Age // 0
417+
418+// Optional field checks
419+
420+res.JSON.Owners.Valid() // true
421+res.JSON.Name.Valid() // false
422+res.JSON.Age.Valid() // false
423+
424+// Raw JSON values
425+
426+res.JSON.Owners.Raw() // "1"
427+res.JSON.Name.Raw() == "null" // true
428+res.JSON.Name.Raw() == respjson.Null // true
429+res.JSON.Age.Raw() == "" // true
430+res.JSON.Age.Raw() == respjson.Omitted // true
404```
431```
405
432
406These `.JSON` structs also include an `ExtraFields` map containing
433These `.JSON` structs also include an `ExtraFields` map containing
@@ -423,31 +450,27 @@ the properties but prefixed with `Of` and feature the tag `json:"...,inline"`.
423
450
424```go
451```go
425type AnimalUnion struct {
452type AnimalUnion struct {
426− OfString string `json:",inline"`
453+ // From variants [Dog], [Cat]
427− Name string `json:"name"`
428− Owner Person `json:"owner"`
454+ Owner Person `json:"owner"`
455+ // From variant [Dog]
456+ DogBreed string `json:"dog_breed"`
457+ // From variant [Cat]
458+ CatBreed string `json:"cat_breed"`
429 // ...
459 // ...
460+
430 JSON struct {
461 JSON struct {
431− OfString resp.Field
462+ Owner respjson.Field
432− Name resp.Field
433− Owner resp.Field
434 // ...
463 // ...
435− }
464+ } `json:"-"`
436}
465}
437
466
438// If animal variant
467// If animal variant
439−if animal.Owner.Address.JSON.ZipCode == "" {
468+if animal.Owner.Address.ZipCode == "" {
440 panic("missing zip code")
469 panic("missing zip code")
441}
470}
442
471
443−// If string variant
444−if !animal.OfString == "" {
445− panic("expected a name")
446−}
447−
448// Switch on the variant
472// Switch on the variant
449−switch variant := animalOrName.AsAny().(type) {
473+switch variant := animal.AsAny().(type) {
450−case string:
451case Dog:
474case Dog:
452case Cat:
475case Cat:
453default:
476default:
@@ -476,6 +499,8 @@ client.Chat.Completions.New(context.TODO(), ...,
476)
499)
477```
500```
478
501
502+The request option `option.WithDebugLog(nil)` may be helpful while debugging.
503+
479See the [full list of request options](https://pkg.go.dev/github.com/openai/openai-go/option).
504See the [full list of request options](https://pkg.go.dev/github.com/openai/openai-go/option).
480
505
481### Pagination
506### Pagination
@@ -527,7 +552,7 @@ To handle errors, we recommend that you use the `errors.As` pattern:
527
552
528```go
553```go
529_, err := client.FineTuning.Jobs.New(context.TODO(), openai.FineTuningJobNewParams{
554_, err := client.FineTuning.Jobs.New(context.TODO(), openai.FineTuningJobNewParams{
530− Model: "babbage-002",
555+ Model: openai.FineTuningJobNewParamsModelBabbage002,
531 TrainingFile: "file-abc123",
556 TrainingFile: "file-abc123",
532})
557})
533if err != nil {
558if err != nil {
@@ -564,7 +589,7 @@ client.Chat.Completions.New(
564 },
589 },
565 },
590 },
566 }},
591 }},
567− Model: shared.ChatModelO3Mini,
592+ Model: shared.ChatModelGPT4_1,
568 },
593 },
569 // This sets the per-retry timeout
594 // This sets the per-retry timeout
570 option.WithRequestTimeout(20*time.Second),
595 option.WithRequestTimeout(20*time.Second),
@@ -581,30 +606,145 @@ The file name and content-type can be customized by implementing `Name() string`
581string` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a
606string` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a
582file returned by `os.Open` will be sent with the file name on disk.
607file returned by `os.Open` will be sent with the file name on disk.
583
608
584−We also provide a helper `openai.FileParam(reader io.Reader, filename string, contentType string)`
609+We also provide a helper `openai.File(reader io.Reader, filename string, contentType string)`
585which can be used to wrap any `io.Reader` with the appropriate file name and content type.
610which can be used to wrap any `io.Reader` with the appropriate file name and content type.
586
611
587```go
612```go
588// A file from the file system
613// A file from the file system
589file, err := os.Open("input.jsonl")
614file, err := os.Open("input.jsonl")
590openai.FileNewParams{
615openai.FileNewParams{
591− File: openai.F[io.Reader](file),
616+ File: file,
592 Purpose: openai.FilePurposeFineTune,
617 Purpose: openai.FilePurposeFineTune,
593}
618}
594
619
595// A file from a string
620// A file from a string
596openai.FileNewParams{
621openai.FileNewParams{
597− File: openai.F[io.Reader](strings.NewReader("my file contents")),
622+ File: strings.NewReader("my file contents"),
598 Purpose: openai.FilePurposeFineTune,
623 Purpose: openai.FilePurposeFineTune,
599}
624}
600
625
601// With a custom filename and contentType
626// With a custom filename and contentType
602openai.FileNewParams{
627openai.FileNewParams{
603− File: openai.FileParam(strings.NewReader(`{"hello": "foo"}`), "file.go", "application/json"),
628+ File: openai.File(strings.NewReader(`{"hello": "foo"}`), "file.go", "application/json"),
604 Purpose: openai.FilePurposeFineTune,
629 Purpose: openai.FilePurposeFineTune,
605}
630}
606```
631```
607
632
633+## Webhook Verification
634+
635+Verifying webhook signatures is _optional but encouraged_.
636+
637+For more information about webhooks, see [the API docs](https://platform.openai.com/docs/guides/webhooks).
638+
639+### Parsing webhook payloads
640+
641+For most use cases, you will likely want to verify the webhook and parse the payload at the same time. To achieve this, we provide the method `client.Webhooks.Unwrap()`, which parses a webhook request and verifies that it was sent by OpenAI. This method will return an error if the signature is invalid.
642+
643+Note that the `body` parameter should be the raw JSON bytes sent from the server (do not parse it first). The `Unwrap()` method will parse this JSON for you into an event object after verifying the webhook was sent from OpenAI.
644+
645+```go
646+package main
647+
648+import (
649+ "io"
650+ "log"
651+ "net/http"
652+ "os"
653+
654+ "github.com/gin-gonic/gin"
655+ "github.com/openai/openai-go"
656+ "github.com/openai/openai-go/option"
657+ "github.com/openai/openai-go/webhooks"
658+)
659+
660+func main() {
661+ client := openai.NewClient(
662+ option.WithWebhookSecret(os.Getenv("OPENAI_WEBHOOK_SECRET")), // env var used by default; explicit here.
663+ )
664+
665+ r := gin.Default()
666+
667+ r.POST("/webhook", func(c *gin.Context) {
668+ body, err := io.ReadAll(c.Request.Body)
669+ if err != nil {
670+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Error reading request body"})
671+ return
672+ }
673+ defer c.Request.Body.Close()
674+
675+ webhookEvent, err := client.Webhooks.Unwrap(body, c.Request.Header)
676+ if err != nil {
677+ log.Printf("Invalid webhook signature: %v", err)
678+ c.JSON(http.StatusBadRequest, gin.H{"error": "invalid signature"})
679+ return
680+ }
681+
682+ switch event := webhookEvent.AsAny().(type) {
683+ case webhooks.ResponseCompletedWebhookEvent:
684+ log.Printf("Response completed: %+v", event.Data)
685+ case webhooks.ResponseFailedWebhookEvent:
686+ log.Printf("Response failed: %+v", event.Data)
687+ default:
688+ log.Printf("Unhandled event type: %T", event)
689+ }
690+
691+ c.JSON(http.StatusOK, gin.H{"message": "ok"})
692+ })
693+
694+ r.Run(":8000")
695+}
696+```
697+
698+### Verifying webhook payloads directly
699+
700+In some cases, you may want to verify the webhook separately from parsing the payload. If you prefer to handle these steps separately, we provide the method `client.Webhooks.VerifySignature()` to _only verify_ the signature of a webhook request. Like `Unwrap()`, this method will return an error if the signature is invalid.
701+
702+Note that the `body` parameter should be the raw JSON bytes sent from the server (do not parse it first). You will then need to parse the body after verifying the signature.
703+
704+```go
705+package main
706+
707+import (
708+ "encoding/json"
709+ "io"
710+ "log"
711+ "net/http"
712+ "os"
713+
714+ "github.com/gin-gonic/gin"
715+ "github.com/openai/openai-go"
716+ "github.com/openai/openai-go/option"
717+)
718+
719+func main() {
720+ client := openai.NewClient(
721+ option.WithWebhookSecret(os.Getenv("OPENAI_WEBHOOK_SECRET")), // env var used by default; explicit here.
722+ )
723+
724+ r := gin.Default()
725+
726+ r.POST("/webhook", func(c *gin.Context) {
727+ body, err := io.ReadAll(c.Request.Body)
728+ if err != nil {
729+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Error reading request body"})
730+ return
731+ }
732+ defer c.Request.Body.Close()
733+
734+ err = client.Webhooks.VerifySignature(body, c.Request.Header)
735+ if err != nil {
736+ log.Printf("Invalid webhook signature: %v", err)
737+ c.JSON(http.StatusBadRequest, gin.H{"error": "invalid signature"})
738+ return
739+ }
740+
741+ c.JSON(http.StatusOK, gin.H{"message": "ok"})
742+ })
743+
744+ r.Run(":8000")
745+}
746+```
747+
608### Retries
748### Retries
609
749
610Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
750Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
@@ -630,7 +770,7 @@ client.Chat.Completions.New(
630 },
770 },
631 },
771 },
632 }},
772 }},
633− Model: shared.ChatModelO3Mini,
773+ Model: shared.ChatModelGPT4_1,
634 },
774 },
635 option.WithMaxRetries(5),
775 option.WithMaxRetries(5),
636)
776)
@@ -654,7 +794,7 @@ chatCompletion, err := client.Chat.Completions.New(
654 },
794 },
655 },
795 },
656 }},
796 }},
657− Model: shared.ChatModelO3Mini,
797+ Model: shared.ChatModelGPT4_1,
658 },
798 },
659 option.WithResponseInto(&response),
799 option.WithResponseInto(&response),
660)
800)
@@ -681,7 +821,7 @@ To make requests to undocumented endpoints, you can use `client.Get`, `client.Po
681var (
821var (
682 // params can be an io.Reader, a []byte, an encoding/json serializable object,
822 // params can be an io.Reader, a []byte, an encoding/json serializable object,
683 // or a "…Params" struct defined in this library.
823 // or a "…Params" struct defined in this library.
684− params map[string]interface{}
824+ params map[string]any
685
825
686 // result can be an []byte, *http.Response, a encoding/json deserializable object,
826 // result can be an []byte, *http.Response, a encoding/json deserializable object,
687 // or a model defined in this library.
827 // or a model defined in this library.
vendor/github.com/openai/openai-go/SECURITY.md+2−2
@@ -16,13 +16,13 @@ before making any information public.
16## Reporting Non-SDK Related Security Issues
16## Reporting Non-SDK Related Security Issues
17
17
18If you encounter security issues that are not directly related to SDKs but pertain to the services
18If you encounter security issues that are not directly related to SDKs but pertain to the services
19−or products provided by OpenAI please follow the respective company's security reporting guidelines.
19+or products provided by OpenAI, please follow the respective company's security reporting guidelines.
20
20
21### OpenAI Terms and Policies
21### OpenAI Terms and Policies
22
22
23Our Security Policy can be found at [Security Policy URL](https://openai.com/policies/coordinated-vulnerability-disclosure-policy).
23Our Security Policy can be found at [Security Policy URL](https://openai.com/policies/coordinated-vulnerability-disclosure-policy).
24
24
25−Please contact disclosure@openai.com for any questions or concerns regarding security of our services.
25+Please contact disclosure@openai.com for any questions or concerns regarding the security of our services.
26
26
27---
27---
28
28
vendor/github.com/openai/openai-go/aliases.go+76−24
@@ -5,7 +5,6 @@ package openai
5import (
5import (
6 "github.com/openai/openai-go/internal/apierror"
6 "github.com/openai/openai-go/internal/apierror"
7 "github.com/openai/openai-go/packages/param"
7 "github.com/openai/openai-go/packages/param"
8− "github.com/openai/openai-go/packages/resp"
9 "github.com/openai/openai-go/shared"
8 "github.com/openai/openai-go/shared"
10)
9)
11
10
@@ -20,6 +19,36 @@ type Error = apierror.Error
20// This is an alias to an internal type.
19// This is an alias to an internal type.
21type ChatModel = shared.ChatModel
20type ChatModel = shared.ChatModel
22
21
22+// Equals "gpt-4.1"
23+const ChatModelGPT4_1 = shared.ChatModelGPT4_1
24+
25+// Equals "gpt-4.1-mini"
26+const ChatModelGPT4_1Mini = shared.ChatModelGPT4_1Mini
27+
28+// Equals "gpt-4.1-nano"
29+const ChatModelGPT4_1Nano = shared.ChatModelGPT4_1Nano
30+
31+// Equals "gpt-4.1-2025-04-14"
32+const ChatModelGPT4_1_2025_04_14 = shared.ChatModelGPT4_1_2025_04_14
33+
34+// Equals "gpt-4.1-mini-2025-04-14"
35+const ChatModelGPT4_1Mini2025_04_14 = shared.ChatModelGPT4_1Mini2025_04_14
36+
37+// Equals "gpt-4.1-nano-2025-04-14"
38+const ChatModelGPT4_1Nano2025_04_14 = shared.ChatModelGPT4_1Nano2025_04_14
39+
40+// Equals "o4-mini"
41+const ChatModelO4Mini = shared.ChatModelO4Mini
42+
43+// Equals "o4-mini-2025-04-16"
44+const ChatModelO4Mini2025_04_16 = shared.ChatModelO4Mini2025_04_16
45+
46+// Equals "o3"
47+const ChatModelO3 = shared.ChatModelO3
48+
49+// Equals "o3-2025-04-16"
50+const ChatModelO3_2025_04_16 = shared.ChatModelO3_2025_04_16
51+
23// Equals "o3-mini"
52// Equals "o3-mini"
24const ChatModelO3Mini = shared.ChatModelO3Mini
53const ChatModelO3Mini = shared.ChatModelO3Mini
25
54
@@ -65,6 +94,9 @@ const ChatModelGPT4oAudioPreview2024_10_01 = shared.ChatModelGPT4oAudioPreview20
65// Equals "gpt-4o-audio-preview-2024-12-17"
94// Equals "gpt-4o-audio-preview-2024-12-17"
66const ChatModelGPT4oAudioPreview2024_12_17 = shared.ChatModelGPT4oAudioPreview2024_12_17
95const ChatModelGPT4oAudioPreview2024_12_17 = shared.ChatModelGPT4oAudioPreview2024_12_17
67
96
97+// Equals "gpt-4o-audio-preview-2025-06-03"
98+const ChatModelGPT4oAudioPreview2025_06_03 = shared.ChatModelGPT4oAudioPreview2025_06_03
99+
68// Equals "gpt-4o-mini-audio-preview"
100// Equals "gpt-4o-mini-audio-preview"
69const ChatModelGPT4oMiniAudioPreview = shared.ChatModelGPT4oMiniAudioPreview
101const ChatModelGPT4oMiniAudioPreview = shared.ChatModelGPT4oMiniAudioPreview
70
102
@@ -86,6 +118,9 @@ const ChatModelGPT4oMiniSearchPreview2025_03_11 = shared.ChatModelGPT4oMiniSearc
86// Equals "chatgpt-4o-latest"
118// Equals "chatgpt-4o-latest"
87const ChatModelChatgpt4oLatest = shared.ChatModelChatgpt4oLatest
119const ChatModelChatgpt4oLatest = shared.ChatModelChatgpt4oLatest
88
120
121+// Equals "codex-mini-latest"
122+const ChatModelCodexMiniLatest = shared.ChatModelCodexMiniLatest
123+
89// Equals "gpt-4o-mini"
124// Equals "gpt-4o-mini"
90const ChatModelGPT4oMini = shared.ChatModelGPT4oMini
125const ChatModelGPT4oMini = shared.ChatModelGPT4oMini
91
126
@@ -254,16 +289,6 @@ type FunctionParameters = shared.FunctionParameters
254// This is an alias to an internal type.
289// This is an alias to an internal type.
255type Metadata = shared.Metadata
290type Metadata = shared.Metadata
256
291
257−// Set of 16 key-value pairs that can be attached to an object. This can be useful
258−// for storing additional information about the object in a structured format, and
259−// querying for objects via API or the dashboard.
260−//
261−// Keys are strings with a maximum length of 64 characters. Values are strings with
262−// a maximum length of 512 characters.
263−//
264−// This is an alias to an internal type.
265−type MetadataParam = shared.MetadataParam
266−
267// **o-series models only**
292// **o-series models only**
268//
293//
269// Configuration options for
294// Configuration options for
@@ -272,21 +297,40 @@ type MetadataParam = shared.MetadataParam
272// This is an alias to an internal type.
297// This is an alias to an internal type.
273type Reasoning = shared.Reasoning
298type Reasoning = shared.Reasoning
274
299
275−// **computer_use_preview only**
300+// **Deprecated:** use `summary` instead.
276//
301//
277// A summary of the reasoning performed by the model. This can be useful for
302// A summary of the reasoning performed by the model. This can be useful for
278−// debugging and understanding the model's reasoning process. One of `concise` or
303+// debugging and understanding the model's reasoning process. One of `auto`,
279−// `detailed`.
304+// `concise`, or `detailed`.
280//
305//
281// This is an alias to an internal type.
306// This is an alias to an internal type.
282type ReasoningGenerateSummary = shared.ReasoningGenerateSummary
307type ReasoningGenerateSummary = shared.ReasoningGenerateSummary
283
308
309+// Equals "auto"
310+const ReasoningGenerateSummaryAuto = shared.ReasoningGenerateSummaryAuto
311+
284// Equals "concise"
312// Equals "concise"
285const ReasoningGenerateSummaryConcise = shared.ReasoningGenerateSummaryConcise
313const ReasoningGenerateSummaryConcise = shared.ReasoningGenerateSummaryConcise
286
314
287// Equals "detailed"
315// Equals "detailed"
288const ReasoningGenerateSummaryDetailed = shared.ReasoningGenerateSummaryDetailed
316const ReasoningGenerateSummaryDetailed = shared.ReasoningGenerateSummaryDetailed
289
317
318+// A summary of the reasoning performed by the model. This can be useful for
319+// debugging and understanding the model's reasoning process. One of `auto`,
320+// `concise`, or `detailed`.
321+//
322+// This is an alias to an internal type.
323+type ReasoningSummary = shared.ReasoningSummary
324+
325+// Equals "auto"
326+const ReasoningSummaryAuto = shared.ReasoningSummaryAuto
327+
328+// Equals "concise"
329+const ReasoningSummaryConcise = shared.ReasoningSummaryConcise
330+
331+// Equals "detailed"
332+const ReasoningSummaryDetailed = shared.ReasoningSummaryDetailed
333+
290// **o-series models only**
334// **o-series models only**
291//
335//
292// Configuration options for
336// Configuration options for
@@ -371,18 +415,26 @@ const ResponsesModelO1Pro = shared.ResponsesModelO1Pro
371// Equals "o1-pro-2025-03-19"
415// Equals "o1-pro-2025-03-19"
372const ResponsesModelO1Pro2025_03_19 = shared.ResponsesModelO1Pro2025_03_19
416const ResponsesModelO1Pro2025_03_19 = shared.ResponsesModelO1Pro2025_03_19
373
417
418+// Equals "o3-pro"
419+const ResponsesModelO3Pro = shared.ResponsesModelO3Pro
420+
421+// Equals "o3-pro-2025-06-10"
422+const ResponsesModelO3Pro2025_06_10 = shared.ResponsesModelO3Pro2025_06_10
423+
424+// Equals "o3-deep-research"
425+const ResponsesModelO3DeepResearch = shared.ResponsesModelO3DeepResearch
426+
427+// Equals "o3-deep-research-2025-06-26"
428+const ResponsesModelO3DeepResearch2025_06_26 = shared.ResponsesModelO3DeepResearch2025_06_26
429+
430+// Equals "o4-mini-deep-research"
431+const ResponsesModelO4MiniDeepResearch = shared.ResponsesModelO4MiniDeepResearch
432+
433+// Equals "o4-mini-deep-research-2025-06-26"
434+const ResponsesModelO4MiniDeepResearch2025_06_26 = shared.ResponsesModelO4MiniDeepResearch2025_06_26
435+
374// Equals "computer-use-preview"
436// Equals "computer-use-preview"
375const ResponsesModelComputerUsePreview = shared.ResponsesModelComputerUsePreview
437const ResponsesModelComputerUsePreview = shared.ResponsesModelComputerUsePreview
376
438
377// Equals "computer-use-preview-2025-03-11"
439// Equals "computer-use-preview-2025-03-11"
378const ResponsesModelComputerUsePreview2025_03_11 = shared.ResponsesModelComputerUsePreview2025_03_11
440const ResponsesModelComputerUsePreview2025_03_11 = shared.ResponsesModelComputerUsePreview2025_03_11
379−
380−func toParam[T comparable](value T, meta resp.Field) param.Opt[T] {
381− if meta.IsPresent() {
382− return param.NewOpt(value)
383− }
384− if meta.IsExplicitNull() {
385− return param.NullOpt[T]()
386− }
387− return param.Opt[T]{}
388−}
vendor/github.com/openai/openai-go/api.md+170−2
@@ -5,7 +5,7 @@
5- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#CompoundFilterParam">CompoundFilterParam</a>
5- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#CompoundFilterParam">CompoundFilterParam</a>
6- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#FunctionDefinitionParam">FunctionDefinitionParam</a>
6- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#FunctionDefinitionParam">FunctionDefinitionParam</a>
7- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#FunctionParameters">FunctionParameters</a>
7- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#FunctionParameters">FunctionParameters</a>
8−- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#MetadataParam">MetadataParam</a>
8+- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#Metadata">Metadata</a>
9- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#ReasoningParam">ReasoningParam</a>
9- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#ReasoningParam">ReasoningParam</a>
10- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#ReasoningEffort">ReasoningEffort</a>
10- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#ReasoningEffort">ReasoningEffort</a>
11- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#ResponseFormatJSONObjectParam">ResponseFormatJSONObjectParam</a>
11- <a href="https://pkg.go.dev/github.com/openai/openai-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/shared#ResponseFormatJSONObjectParam">ResponseFormatJSONObjectParam</a>
@@ -221,6 +221,26 @@ Methods:
221
221
222# FineTuning
222# FineTuning
223
223
224+## Methods
225+
226+Params Types:
227+
228+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#DpoHyperparameters">DpoHyperparameters</a>
229+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#DpoMethodParam">DpoMethodParam</a>
230+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ReinforcementHyperparameters">ReinforcementHyperparameters</a>
231+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ReinforcementMethodParam">ReinforcementMethodParam</a>
232+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#SupervisedHyperparameters">SupervisedHyperparameters</a>
233+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#SupervisedMethodParam">SupervisedMethodParam</a>
234+
235+Response Types:
236+
237+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#DpoHyperparametersResp">DpoHyperparametersResp</a>
238+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#DpoMethod">DpoMethod</a>
239+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ReinforcementHyperparametersResp">ReinforcementHyperparametersResp</a>
240+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ReinforcementMethod">ReinforcementMethod</a>
241+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#SupervisedHyperparametersResp">SupervisedHyperparametersResp</a>
242+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#SupervisedMethod">SupervisedMethod</a>
243+
224## Jobs
244## Jobs
225
245
226Response Types:
246Response Types:
@@ -237,6 +257,8 @@ Methods:
237- <code title="get /fine_tuning/jobs">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobListParams">FineTuningJobListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJob">FineTuningJob</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
257- <code title="get /fine_tuning/jobs">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobListParams">FineTuningJobListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJob">FineTuningJob</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
238- <code title="post /fine_tuning/jobs/{fine_tuning_job_id}/cancel">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.Cancel">Cancel</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJob">FineTuningJob</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
258- <code title="post /fine_tuning/jobs/{fine_tuning_job_id}/cancel">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.Cancel">Cancel</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJob">FineTuningJob</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
239- <code title="get /fine_tuning/jobs/{fine_tuning_job_id}/events">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.ListEvents">ListEvents</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobListEventsParams">FineTuningJobListEventsParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobEvent">FineTuningJobEvent</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
259- <code title="get /fine_tuning/jobs/{fine_tuning_job_id}/events">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.ListEvents">ListEvents</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobListEventsParams">FineTuningJobListEventsParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobEvent">FineTuningJobEvent</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
260+- <code title="post /fine_tuning/jobs/{fine_tuning_job_id}/pause">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.Pause">Pause</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJob">FineTuningJob</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
261+- <code title="post /fine_tuning/jobs/{fine_tuning_job_id}/resume">client.FineTuning.Jobs.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobService.Resume">Resume</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJob">FineTuningJob</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
240
262
241### Checkpoints
263### Checkpoints
242
264
@@ -248,6 +270,58 @@ Methods:
248
270
249- <code title="get /fine_tuning/jobs/{fine_tuning_job_id}/checkpoints">client.FineTuning.Jobs.Checkpoints.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobCheckpointService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobCheckpointListParams">FineTuningJobCheckpointListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobCheckpoint">FineTuningJobCheckpoint</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
271- <code title="get /fine_tuning/jobs/{fine_tuning_job_id}/checkpoints">client.FineTuning.Jobs.Checkpoints.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobCheckpointService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTuningJobID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobCheckpointListParams">FineTuningJobCheckpointListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningJobCheckpoint">FineTuningJobCheckpoint</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
250
272
273+## Checkpoints
274+
275+### Permissions
276+
277+Response Types:
278+
279+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionNewResponse">FineTuningCheckpointPermissionNewResponse</a>
280+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionGetResponse">FineTuningCheckpointPermissionGetResponse</a>
281+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionDeleteResponse">FineTuningCheckpointPermissionDeleteResponse</a>
282+
283+Methods:
284+
285+- <code title="post /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions">client.FineTuning.Checkpoints.Permissions.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTunedModelCheckpoint <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionNewParams">FineTuningCheckpointPermissionNewParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#Page">Page</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionNewResponse">FineTuningCheckpointPermissionNewResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
286+- <code title="get /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions">client.FineTuning.Checkpoints.Permissions.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTunedModelCheckpoint <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionGetParams">FineTuningCheckpointPermissionGetParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionGetResponse">FineTuningCheckpointPermissionGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
287+- <code title="delete /fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id}">client.FineTuning.Checkpoints.Permissions.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, fineTunedModelCheckpoint <a href="https://pkg.go.dev/builtin#string">string</a>, permissionID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningCheckpointPermissionDeleteResponse">FineTuningCheckpointPermissionDeleteResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
288+
289+## Alpha
290+
291+### Graders
292+
293+Response Types:
294+
295+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderRunResponse">FineTuningAlphaGraderRunResponse</a>
296+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderValidateResponse">FineTuningAlphaGraderValidateResponse</a>
297+
298+Methods:
299+
300+- <code title="post /fine_tuning/alpha/graders/run">client.FineTuning.Alpha.Graders.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderService.Run">Run</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderRunParams">FineTuningAlphaGraderRunParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderRunResponse">FineTuningAlphaGraderRunResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
301+- <code title="post /fine_tuning/alpha/graders/validate">client.FineTuning.Alpha.Graders.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderService.Validate">Validate</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderValidateParams">FineTuningAlphaGraderValidateParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#FineTuningAlphaGraderValidateResponse">FineTuningAlphaGraderValidateResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
302+
303+# Graders
304+
305+## GraderModels
306+
307+Params Types:
308+
309+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#LabelModelGraderParam">LabelModelGraderParam</a>
310+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#MultiGraderParam">MultiGraderParam</a>
311+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#PythonGraderParam">PythonGraderParam</a>
312+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ScoreModelGraderParam">ScoreModelGraderParam</a>
313+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#StringCheckGraderParam">StringCheckGraderParam</a>
314+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#TextSimilarityGraderParam">TextSimilarityGraderParam</a>
315+
316+Response Types:
317+
318+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#LabelModelGrader">LabelModelGrader</a>
319+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#MultiGrader">MultiGrader</a>
320+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#PythonGrader">PythonGrader</a>
321+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ScoreModelGrader">ScoreModelGrader</a>
322+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#StringCheckGrader">StringCheckGrader</a>
323+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#TextSimilarityGrader">TextSimilarityGrader</a>
324+
251# VectorStores
325# VectorStores
252
326
253Params Types:
327Params Types:
@@ -306,6 +380,35 @@ Methods:
306- <code title="post /vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel">client.VectorStores.FileBatches.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatchService.Cancel">Cancel</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, vectorStoreID <a href="https://pkg.go.dev/builtin#string">string</a>, batchID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatch">VectorStoreFileBatch</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
380- <code title="post /vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel">client.VectorStores.FileBatches.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatchService.Cancel">Cancel</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, vectorStoreID <a href="https://pkg.go.dev/builtin#string">string</a>, batchID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatch">VectorStoreFileBatch</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
307- <code title="get /vector_stores/{vector_store_id}/file_batches/{batch_id}/files">client.VectorStores.FileBatches.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatchService.ListFiles">ListFiles</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, vectorStoreID <a href="https://pkg.go.dev/builtin#string">string</a>, batchID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatchListFilesParams">VectorStoreFileBatchListFilesParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFile">VectorStoreFile</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
381- <code title="get /vector_stores/{vector_store_id}/file_batches/{batch_id}/files">client.VectorStores.FileBatches.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatchService.ListFiles">ListFiles</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, vectorStoreID <a href="https://pkg.go.dev/builtin#string">string</a>, batchID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFileBatchListFilesParams">VectorStoreFileBatchListFilesParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#VectorStoreFile">VectorStoreFile</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
308
382
383+# Webhooks
384+
385+Response Types:
386+
387+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#BatchCancelledWebhookEvent">BatchCancelledWebhookEvent</a>
388+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#BatchCompletedWebhookEvent">BatchCompletedWebhookEvent</a>
389+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#BatchExpiredWebhookEvent">BatchExpiredWebhookEvent</a>
390+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#BatchFailedWebhookEvent">BatchFailedWebhookEvent</a>
391+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#EvalRunCanceledWebhookEvent">EvalRunCanceledWebhookEvent</a>
392+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#EvalRunFailedWebhookEvent">EvalRunFailedWebhookEvent</a>
393+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#EvalRunSucceededWebhookEvent">EvalRunSucceededWebhookEvent</a>
394+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#FineTuningJobCancelledWebhookEvent">FineTuningJobCancelledWebhookEvent</a>
395+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#FineTuningJobFailedWebhookEvent">FineTuningJobFailedWebhookEvent</a>
396+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#FineTuningJobSucceededWebhookEvent">FineTuningJobSucceededWebhookEvent</a>
397+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#ResponseCancelledWebhookEvent">ResponseCancelledWebhookEvent</a>
398+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#ResponseCompletedWebhookEvent">ResponseCompletedWebhookEvent</a>
399+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#ResponseFailedWebhookEvent">ResponseFailedWebhookEvent</a>
400+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#ResponseIncompleteWebhookEvent">ResponseIncompleteWebhookEvent</a>
401+- <a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#UnwrapWebhookEventUnion">UnwrapWebhookEventUnion</a>
402+
403+Methods:
404+
405+- <code>client.Webhooks.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#WebhookService.Unwrap">Unwrap</a>(body []<a href="https://pkg.go.dev/builtin#byte">byte</a>, headers <a href="https://pkg.go.dev/net/http">http</a>.<a href="https://pkg.go.dev/net/http#Header">Header</a>, opts ...<a href="https://pkg.go.dev/github.com/openai/openai-go/option">option</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/option#RequestOption">RequestOption</a>) (*<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#UnwrapWebhookEventUnion">UnwrapWebhookEventUnion</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
406+- <code>client.Webhooks.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#WebhookService.UnwrapWithTolerance">UnwrapWithTolerance</a>(body []<a href="https://pkg.go.dev/builtin#byte">byte</a>, headers <a href="https://pkg.go.dev/net/http">http</a>.<a href="https://pkg.go.dev/net/http#Header">Header</a>, tolerance <a href="https://pkg.go.dev/time">time</a>.<a href="https://pkg.go.dev/time#Duration">Duration</a>, opts ...<a href="https://pkg.go.dev/github.com/openai/openai-go/option">option</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/option#RequestOption">RequestOption</a>) (*<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#UnwrapWebhookEventUnion">UnwrapWebhookEventUnion</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
407+- <code>client.Webhooks.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#WebhookService.UnwrapWithToleranceAndTime">UnwrapWithToleranceAndTime</a>(body []<a href="https://pkg.go.dev/builtin#byte">byte</a>, headers <a href="https://pkg.go.dev/net/http">http</a>.<a href="https://pkg.go.dev/net/http#Header">Header</a>, tolerance <a href="https://pkg.go.dev/time">time</a>.<a href="https://pkg.go.dev/time#Duration">Duration</a>, now <a href="https://pkg.go.dev/time">time</a>.<a href="https://pkg.go.dev/time#Time">Time</a>, opts ...<a href="https://pkg.go.dev/github.com/openai/openai-go/option">option</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/option#RequestOption">RequestOption</a>) (*<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks">webhooks</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#UnwrapWebhookEventUnion">UnwrapWebhookEventUnion</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
408+- <code>client.Webhooks.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#WebhookService.VerifySignature">VerifySignature</a>(body []<a href="https://pkg.go.dev/builtin#byte">byte</a>, headers <a href="https://pkg.go.dev/net/http">http</a>.<a href="https://pkg.go.dev/net/http#Header">Header</a>, opts ...<a href="https://pkg.go.dev/github.com/openai/openai-go/option">option</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/option#RequestOption">RequestOption</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
409+- <code>client.Webhooks.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#WebhookService.VerifySignatureWithTolerance">VerifySignatureWithTolerance</a>(body []<a href="https://pkg.go.dev/builtin#byte">byte</a>, headers <a href="https://pkg.go.dev/net/http">http</a>.<a href="https://pkg.go.dev/net/http#Header">Header</a>, tolerance <a href="https://pkg.go.dev/time">time</a>.<a href="https://pkg.go.dev/time#Duration">Duration</a>, opts ...<a href="https://pkg.go.dev/github.com/openai/openai-go/option">option</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/option#RequestOption">RequestOption</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
410+- <code>client.Webhooks.<a href="https://pkg.go.dev/github.com/openai/openai-go/webhooks#WebhookService.VerifySignatureWithToleranceAndTime">VerifySignatureWithToleranceAndTime</a>(body []<a href="https://pkg.go.dev/builtin#byte">byte</a>, headers <a href="https://pkg.go.dev/net/http">http</a>.<a href="https://pkg.go.dev/net/http#Header">Header</a>, tolerance <a href="https://pkg.go.dev/time">time</a>.<a href="https://pkg.go.dev/time#Duration">Duration</a>, now <a href="https://pkg.go.dev/time">time</a>.<a href="https://pkg.go.dev/time#Time">Time</a>, opts ...<a href="https://pkg.go.dev/github.com/openai/openai-go/option">option</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/option#RequestOption">RequestOption</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
411+
309# Beta
412# Beta
310
413
311## Assistants
414## Assistants
@@ -502,6 +605,7 @@ Params Types:
502- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#EasyInputMessageParam">EasyInputMessageParam</a>
605- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#EasyInputMessageParam">EasyInputMessageParam</a>
503- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FileSearchToolParam">FileSearchToolParam</a>
606- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FileSearchToolParam">FileSearchToolParam</a>
504- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FunctionToolParam">FunctionToolParam</a>
607- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FunctionToolParam">FunctionToolParam</a>
608+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseCodeInterpreterToolCallParam">ResponseCodeInterpreterToolCallParam</a>
505- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseComputerToolCallParam">ResponseComputerToolCallParam</a>
609- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseComputerToolCallParam">ResponseComputerToolCallParam</a>
506- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseComputerToolCallOutputScreenshotParam">ResponseComputerToolCallOutputScreenshotParam</a>
610- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseComputerToolCallOutputScreenshotParam">ResponseComputerToolCallOutputScreenshotParam</a>
507- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFileSearchToolCallParam">ResponseFileSearchToolCallParam</a>
611- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFileSearchToolCallParam">ResponseFileSearchToolCallParam</a>
@@ -520,10 +624,12 @@ Params Types:
520- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputMessageParam">ResponseOutputMessageParam</a>
624- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputMessageParam">ResponseOutputMessageParam</a>
521- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputRefusalParam">ResponseOutputRefusalParam</a>
625- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputRefusalParam">ResponseOutputRefusalParam</a>
522- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputTextParam">ResponseOutputTextParam</a>
626- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputTextParam">ResponseOutputTextParam</a>
627+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponsePromptParam">ResponsePromptParam</a>
523- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningItemParam">ResponseReasoningItemParam</a>
628- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningItemParam">ResponseReasoningItemParam</a>
524- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextConfigParam">ResponseTextConfigParam</a>
629- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextConfigParam">ResponseTextConfigParam</a>
525- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolUnionParam">ToolUnionParam</a>
630- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolUnionParam">ToolUnionParam</a>
526- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceFunctionParam">ToolChoiceFunctionParam</a>
631- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceFunctionParam">ToolChoiceFunctionParam</a>
632+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceMcpParam">ToolChoiceMcpParam</a>
527- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceOptions">ToolChoiceOptions</a>
633- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceOptions">ToolChoiceOptions</a>
528- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceTypesParam">ToolChoiceTypesParam</a>
634- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceTypesParam">ToolChoiceTypesParam</a>
529- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#WebSearchToolParam">WebSearchToolParam</a>
635- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#WebSearchToolParam">WebSearchToolParam</a>
@@ -531,6 +637,7 @@ Params Types:
531Response Types:
637Response Types:
532
638
533- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ComputerTool">ComputerTool</a>
639- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ComputerTool">ComputerTool</a>
640+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#EasyInputMessage">EasyInputMessage</a>
534- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FileSearchTool">FileSearchTool</a>
641- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FileSearchTool">FileSearchTool</a>
535- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FunctionTool">FunctionTool</a>
642- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#FunctionTool">FunctionTool</a>
536- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>
643- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>
@@ -566,27 +673,50 @@ Response Types:
566- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFunctionToolCallItem">ResponseFunctionToolCallItem</a>
673- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFunctionToolCallItem">ResponseFunctionToolCallItem</a>
567- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFunctionToolCallOutputItem">ResponseFunctionToolCallOutputItem</a>
674- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFunctionToolCallOutputItem">ResponseFunctionToolCallOutputItem</a>
568- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFunctionWebSearch">ResponseFunctionWebSearch</a>
675- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseFunctionWebSearch">ResponseFunctionWebSearch</a>
676+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseImageGenCallCompletedEvent">ResponseImageGenCallCompletedEvent</a>
677+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseImageGenCallGeneratingEvent">ResponseImageGenCallGeneratingEvent</a>
678+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseImageGenCallInProgressEvent">ResponseImageGenCallInProgressEvent</a>
679+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseImageGenCallPartialImageEvent">ResponseImageGenCallPartialImageEvent</a>
569- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInProgressEvent">ResponseInProgressEvent</a>
680- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInProgressEvent">ResponseInProgressEvent</a>
570- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseIncompleteEvent">ResponseIncompleteEvent</a>
681- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseIncompleteEvent">ResponseIncompleteEvent</a>
571- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputContentUnion">ResponseInputContentUnion</a>
682- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputContentUnion">ResponseInputContentUnion</a>
572- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputFile">ResponseInputFile</a>
683- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputFile">ResponseInputFile</a>
573- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputImage">ResponseInputImage</a>
684- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputImage">ResponseInputImage</a>
685+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputItemUnion">ResponseInputItemUnion</a>
574- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputMessageContentList">ResponseInputMessageContentList</a>
686- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputMessageContentList">ResponseInputMessageContentList</a>
575- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputMessageItem">ResponseInputMessageItem</a>
687- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputMessageItem">ResponseInputMessageItem</a>
576- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputText">ResponseInputText</a>
688- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseInputText">ResponseInputText</a>
577- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseItemUnion">ResponseItemUnion</a>
689- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseItemUnion">ResponseItemUnion</a>
690+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpCallArgumentsDeltaEvent">ResponseMcpCallArgumentsDeltaEvent</a>
691+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpCallArgumentsDoneEvent">ResponseMcpCallArgumentsDoneEvent</a>
692+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpCallCompletedEvent">ResponseMcpCallCompletedEvent</a>
693+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpCallFailedEvent">ResponseMcpCallFailedEvent</a>
694+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpCallInProgressEvent">ResponseMcpCallInProgressEvent</a>
695+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpListToolsCompletedEvent">ResponseMcpListToolsCompletedEvent</a>
696+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpListToolsFailedEvent">ResponseMcpListToolsFailedEvent</a>
697+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseMcpListToolsInProgressEvent">ResponseMcpListToolsInProgressEvent</a>
578- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputItemUnion">ResponseOutputItemUnion</a>
698- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputItemUnion">ResponseOutputItemUnion</a>
579- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputItemAddedEvent">ResponseOutputItemAddedEvent</a>
699- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputItemAddedEvent">ResponseOutputItemAddedEvent</a>
580- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputItemDoneEvent">ResponseOutputItemDoneEvent</a>
700- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputItemDoneEvent">ResponseOutputItemDoneEvent</a>
581- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputMessage">ResponseOutputMessage</a>
701- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputMessage">ResponseOutputMessage</a>
582- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputRefusal">ResponseOutputRefusal</a>
702- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputRefusal">ResponseOutputRefusal</a>
583- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputText">ResponseOutputText</a>
703- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputText">ResponseOutputText</a>
704+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseOutputTextAnnotationAddedEvent">ResponseOutputTextAnnotationAddedEvent</a>
705+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponsePrompt">ResponsePrompt</a>
706+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseQueuedEvent">ResponseQueuedEvent</a>
707+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningDeltaEvent">ResponseReasoningDeltaEvent</a>
708+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningDoneEvent">ResponseReasoningDoneEvent</a>
584- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningItem">ResponseReasoningItem</a>
709- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningItem">ResponseReasoningItem</a>
710+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningSummaryDeltaEvent">ResponseReasoningSummaryDeltaEvent</a>
711+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningSummaryDoneEvent">ResponseReasoningSummaryDoneEvent</a>
712+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningSummaryPartAddedEvent">ResponseReasoningSummaryPartAddedEvent</a>
713+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningSummaryPartDoneEvent">ResponseReasoningSummaryPartDoneEvent</a>
714+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningSummaryTextDeltaEvent">ResponseReasoningSummaryTextDeltaEvent</a>
715+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseReasoningSummaryTextDoneEvent">ResponseReasoningSummaryTextDoneEvent</a>
585- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseRefusalDeltaEvent">ResponseRefusalDeltaEvent</a>
716- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseRefusalDeltaEvent">ResponseRefusalDeltaEvent</a>
586- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseRefusalDoneEvent">ResponseRefusalDoneEvent</a>
717- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseRefusalDoneEvent">ResponseRefusalDoneEvent</a>
587- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseStatus">ResponseStatus</a>
718- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseStatus">ResponseStatus</a>
588- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseStreamEventUnion">ResponseStreamEventUnion</a>
719- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseStreamEventUnion">ResponseStreamEventUnion</a>
589−- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextAnnotationDeltaEvent">ResponseTextAnnotationDeltaEvent</a>
590- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextConfig">ResponseTextConfig</a>
720- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextConfig">ResponseTextConfig</a>
591- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextDeltaEvent">ResponseTextDeltaEvent</a>
721- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextDeltaEvent">ResponseTextDeltaEvent</a>
592- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextDoneEvent">ResponseTextDoneEvent</a>
722- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseTextDoneEvent">ResponseTextDoneEvent</a>
@@ -596,6 +726,7 @@ Response Types:
596- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseWebSearchCallSearchingEvent">ResponseWebSearchCallSearchingEvent</a>
726- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseWebSearchCallSearchingEvent">ResponseWebSearchCallSearchingEvent</a>
597- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolUnion">ToolUnion</a>
727- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolUnion">ToolUnion</a>
598- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceFunction">ToolChoiceFunction</a>
728- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceFunction">ToolChoiceFunction</a>
729+- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceMcp">ToolChoiceMcp</a>
599- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceOptions">ToolChoiceOptions</a>
730- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceOptions">ToolChoiceOptions</a>
600- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceTypes">ToolChoiceTypes</a>
731- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ToolChoiceTypes">ToolChoiceTypes</a>
601- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#WebSearchTool">WebSearchTool</a>
732- <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#WebSearchTool">WebSearchTool</a>
@@ -605,6 +736,7 @@ Methods:
605- <code title="post /responses">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseNewParams">ResponseNewParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
736- <code title="post /responses">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseNewParams">ResponseNewParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
606- <code title="get /responses/{response_id}">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseGetParams">ResponseGetParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
737- <code title="get /responses/{response_id}">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseGetParams">ResponseGetParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
607- <code title="delete /responses/{response_id}">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
738- <code title="delete /responses/{response_id}">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
739+- <code title="post /responses/{response_id}/cancel">client.Responses.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseService.Cancel">Cancel</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#Response">Response</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
608
740
609## InputItems
741## InputItems
610
742
@@ -615,3 +747,39 @@ Response Types:
615Methods:
747Methods:
616
748
617- <code title="get /responses/{response_id}/input_items">client.Responses.InputItems.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#InputItemService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#InputItemListParams">InputItemListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseItemUnion">ResponseItemUnion</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
749- <code title="get /responses/{response_id}/input_items">client.Responses.InputItems.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#InputItemService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, responseID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#InputItemListParams">InputItemListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go/responses">responses</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/responses#ResponseItemUnion">ResponseItemUnion</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
750+
751+# Containers
752+
753+Response Types:
754+
755+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerNewResponse">ContainerNewResponse</a>
756+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerGetResponse">ContainerGetResponse</a>
757+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerListResponse">ContainerListResponse</a>
758+
759+Methods:
760+
761+- <code title="post /containers">client.Containers.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerNewParams">ContainerNewParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerNewResponse">ContainerNewResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
762+- <code title="get /containers/{container_id}">client.Containers.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerGetResponse">ContainerGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
763+- <code title="get /containers">client.Containers.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerListParams">ContainerListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerListResponse">ContainerListResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
764+- <code title="delete /containers/{container_id}">client.Containers.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
765+
766+## Files
767+
768+Response Types:
769+
770+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileNewResponse">ContainerFileNewResponse</a>
771+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileGetResponse">ContainerFileGetResponse</a>
772+- <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileListResponse">ContainerFileListResponse</a>
773+
774+Methods:
775+
776+- <code title="post /containers/{container_id}/files">client.Containers.Files.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileNewParams">ContainerFileNewParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileNewResponse">ContainerFileNewResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
777+- <code title="get /containers/{container_id}/files/{file_id}">client.Containers.Files.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>, fileID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileGetResponse">ContainerFileGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
778+- <code title="get /containers/{container_id}/files">client.Containers.Files.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileListParams">ContainerFileListParams</a>) (<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go/packages/pagination#CursorPage">CursorPage</a>[<a href="https://pkg.go.dev/github.com/openai/openai-go">openai</a>.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileListResponse">ContainerFileListResponse</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
779+- <code title="delete /containers/{container_id}/files/{file_id}">client.Containers.Files.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>, fileID <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
780+
781+### Content
782+
783+Methods:
784+
785+- <code title="get /containers/{container_id}/files/{file_id}/content">client.Containers.Files.Content.<a href="https://pkg.go.dev/github.com/openai/openai-go#ContainerFileContentService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, containerID <a href="https://pkg.go.dev/builtin#string">string</a>, fileID <a href="https://pkg.go.dev/builtin#string">string</a>) (http.Response, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
vendor/github.com/openai/openai-go/audiospeech.go+24−11
@@ -6,6 +6,7 @@ import (
6 "context"
6 "context"
7 "net/http"
7 "net/http"
8
8
9+ "github.com/openai/openai-go/internal/apijson"
9 "github.com/openai/openai-go/internal/requestconfig"
10 "github.com/openai/openai-go/internal/requestconfig"
10 "github.com/openai/openai-go/option"
11 "github.com/openai/openai-go/option"
11 "github.com/openai/openai-go/packages/param"
12 "github.com/openai/openai-go/packages/param"
@@ -54,12 +55,9 @@ type AudioSpeechNewParams struct {
54 // `tts-1`, `tts-1-hd` or `gpt-4o-mini-tts`.
55 // `tts-1`, `tts-1-hd` or `gpt-4o-mini-tts`.
55 Model SpeechModel `json:"model,omitzero,required"`
56 Model SpeechModel `json:"model,omitzero,required"`
56 // The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
57 // The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
57− // `coral`, `echo`, `fable`, `onyx`, `nova`, `sage` and `shimmer`. Previews of the
58+ // `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and
58− // voices are available in the
59+ // `verse`. Previews of the voices are available in the
59 // [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
60 // [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
60− //
61− // Any of "alloy", "ash", "coral", "echo", "fable", "onyx", "nova", "sage",
62− // "shimmer".
63 Voice AudioSpeechNewParamsVoice `json:"voice,omitzero,required"`
61 Voice AudioSpeechNewParamsVoice `json:"voice,omitzero,required"`
64 // Control the voice of your generated audio with additional instructions. Does not
62 // Control the voice of your generated audio with additional instructions. Does not
65 // work with `tts-1` or `tts-1-hd`.
63 // work with `tts-1` or `tts-1-hd`.
@@ -72,27 +70,32 @@ type AudioSpeechNewParams struct {
72 //
70 //
73 // Any of "mp3", "opus", "aac", "flac", "wav", "pcm".
71 // Any of "mp3", "opus", "aac", "flac", "wav", "pcm".
74 ResponseFormat AudioSpeechNewParamsResponseFormat `json:"response_format,omitzero"`
72 ResponseFormat AudioSpeechNewParamsResponseFormat `json:"response_format,omitzero"`
73+ // The format to stream the audio in. Supported formats are `sse` and `audio`.
74+ // `sse` is not supported for `tts-1` or `tts-1-hd`.
75+ //
76+ // Any of "sse", "audio".
77+ StreamFormat AudioSpeechNewParamsStreamFormat `json:"stream_format,omitzero"`
75 paramObj
78 paramObj
76}
79}
77
80
78−// IsPresent returns true if the field's value is not omitted and not the JSON
79−// "null". To check if this field is omitted, use [param.IsOmitted].
80−func (f AudioSpeechNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
81−
82func (r AudioSpeechNewParams) MarshalJSON() (data []byte, err error) {
81func (r AudioSpeechNewParams) MarshalJSON() (data []byte, err error) {
83 type shadow AudioSpeechNewParams
82 type shadow AudioSpeechNewParams
84 return param.MarshalObject(r, (*shadow)(&r))
83 return param.MarshalObject(r, (*shadow)(&r))
85}
84}
85+func (r *AudioSpeechNewParams) UnmarshalJSON(data []byte) error {
86+ return apijson.UnmarshalRoot(data, r)
87+}
86
88
87// The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
89// The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
88−// `coral`, `echo`, `fable`, `onyx`, `nova`, `sage` and `shimmer`. Previews of the
90+// `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and
89−// voices are available in the
91+// `verse`. Previews of the voices are available in the
90// [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
92// [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
91type AudioSpeechNewParamsVoice string
93type AudioSpeechNewParamsVoice string
92
94
93const (
95const (
94 AudioSpeechNewParamsVoiceAlloy AudioSpeechNewParamsVoice = "alloy"
96 AudioSpeechNewParamsVoiceAlloy AudioSpeechNewParamsVoice = "alloy"
95 AudioSpeechNewParamsVoiceAsh AudioSpeechNewParamsVoice = "ash"
97 AudioSpeechNewParamsVoiceAsh AudioSpeechNewParamsVoice = "ash"
98+ AudioSpeechNewParamsVoiceBallad AudioSpeechNewParamsVoice = "ballad"
96 AudioSpeechNewParamsVoiceCoral AudioSpeechNewParamsVoice = "coral"
99 AudioSpeechNewParamsVoiceCoral AudioSpeechNewParamsVoice = "coral"
97 AudioSpeechNewParamsVoiceEcho AudioSpeechNewParamsVoice = "echo"
100 AudioSpeechNewParamsVoiceEcho AudioSpeechNewParamsVoice = "echo"
98 AudioSpeechNewParamsVoiceFable AudioSpeechNewParamsVoice = "fable"
101 AudioSpeechNewParamsVoiceFable AudioSpeechNewParamsVoice = "fable"
@@ -100,6 +103,7 @@ const (
100 AudioSpeechNewParamsVoiceNova AudioSpeechNewParamsVoice = "nova"
103 AudioSpeechNewParamsVoiceNova AudioSpeechNewParamsVoice = "nova"
101 AudioSpeechNewParamsVoiceSage AudioSpeechNewParamsVoice = "sage"
104 AudioSpeechNewParamsVoiceSage AudioSpeechNewParamsVoice = "sage"
102 AudioSpeechNewParamsVoiceShimmer AudioSpeechNewParamsVoice = "shimmer"
105 AudioSpeechNewParamsVoiceShimmer AudioSpeechNewParamsVoice = "shimmer"
106+ AudioSpeechNewParamsVoiceVerse AudioSpeechNewParamsVoice = "verse"
103)
107)
104
108
105// The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`,
109// The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`,
@@ -114,3 +118,12 @@ const (
114 AudioSpeechNewParamsResponseFormatWAV AudioSpeechNewParamsResponseFormat = "wav"
118 AudioSpeechNewParamsResponseFormatWAV AudioSpeechNewParamsResponseFormat = "wav"
115 AudioSpeechNewParamsResponseFormatPCM AudioSpeechNewParamsResponseFormat = "pcm"
119 AudioSpeechNewParamsResponseFormatPCM AudioSpeechNewParamsResponseFormat = "pcm"
116)
120)
121+
122+// The format to stream the audio in. Supported formats are `sse` and `audio`.
123+// `sse` is not supported for `tts-1` or `tts-1-hd`.
124+type AudioSpeechNewParamsStreamFormat string
125+
126+const (
127+ AudioSpeechNewParamsStreamFormatSSE AudioSpeechNewParamsStreamFormat = "sse"
128+ AudioSpeechNewParamsStreamFormatAudio AudioSpeechNewParamsStreamFormat = "audio"
129+)
vendor/github.com/openai/openai-go/audiotranscription.go+332−54
@@ -15,7 +15,7 @@ import (
15 "github.com/openai/openai-go/internal/requestconfig"
15 "github.com/openai/openai-go/internal/requestconfig"
16 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/option"
17 "github.com/openai/openai-go/packages/param"
17 "github.com/openai/openai-go/packages/param"
18− "github.com/openai/openai-go/packages/resp"
18+ "github.com/openai/openai-go/packages/respjson"
19 "github.com/openai/openai-go/packages/ssestream"
19 "github.com/openai/openai-go/packages/ssestream"
20 "github.com/openai/openai-go/shared/constant"
20 "github.com/openai/openai-go/shared/constant"
21)
21)
@@ -54,7 +54,9 @@ func (r *AudioTranscriptionService) NewStreaming(ctx context.Context, body Audio
54 err error
54 err error
55 )
55 )
56 opts = append(r.Options[:], opts...)
56 opts = append(r.Options[:], opts...)
57− opts = append([]option.RequestOption{option.WithJSONSet("stream", true)}, opts...)
57+ body.SetExtraFields(map[string]any{
58+ "stream": "true",
59+ })
58 path := "audio/transcriptions"
60 path := "audio/transcriptions"
59 err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &raw, opts...)
61 err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &raw, opts...)
60 return ssestream.NewStream[TranscriptionStreamEventUnion](ssestream.NewDecoder(raw), err)
62 return ssestream.NewStream[TranscriptionStreamEventUnion](ssestream.NewDecoder(raw), err)
@@ -69,12 +71,14 @@ type Transcription struct {
69 // models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe` if `logprobs` is added
71 // models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe` if `logprobs` is added
70 // to the `include` array.
72 // to the `include` array.
71 Logprobs []TranscriptionLogprob `json:"logprobs"`
73 Logprobs []TranscriptionLogprob `json:"logprobs"`
72− // Metadata for the response, check the presence of optional fields with the
74+ // Token usage statistics for the request.
73− // [resp.Field.IsPresent] method.
75+ Usage TranscriptionUsageUnion `json:"usage"`
76+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
74 JSON struct {
77 JSON struct {
75− Text resp.Field
78+ Text respjson.Field
76− Logprobs resp.Field
79+ Logprobs respjson.Field
80+ Usage respjson.Field
77− ExtraFields map[string]resp.Field
81+ ExtraFields map[string]respjson.Field
78 raw string
82 raw string
79 } `json:"-"`
83 } `json:"-"`
80}
84}
@@ -92,13 +96,12 @@ type TranscriptionLogprob struct {
92 Bytes []float64 `json:"bytes"`
96 Bytes []float64 `json:"bytes"`
93 // The log probability of the token.
97 // The log probability of the token.
94 Logprob float64 `json:"logprob"`
98 Logprob float64 `json:"logprob"`
95− // Metadata for the response, check the presence of optional fields with the
99+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
96− // [resp.Field.IsPresent] method.
97 JSON struct {
100 JSON struct {
98− Token resp.Field
101+ Token respjson.Field
99− Bytes resp.Field
102+ Bytes respjson.Field
100− Logprob resp.Field
103+ Logprob respjson.Field
101− ExtraFields map[string]resp.Field
104+ ExtraFields map[string]respjson.Field
102 raw string
105 raw string
103 } `json:"-"`
106 } `json:"-"`
104}
107}
@@ -109,6 +112,153 @@ func (r *TranscriptionLogprob) UnmarshalJSON(data []byte) error {
109 return apijson.UnmarshalRoot(data, r)
112 return apijson.UnmarshalRoot(data, r)
110}
113}
111
114
115+// TranscriptionUsageUnion contains all possible properties and values from
116+// [TranscriptionUsageTokens], [TranscriptionUsageDuration].
117+//
118+// Use the [TranscriptionUsageUnion.AsAny] method to switch on the variant.
119+//
120+// Use the methods beginning with 'As' to cast the union to one of its variants.
121+type TranscriptionUsageUnion struct {
122+ // This field is from variant [TranscriptionUsageTokens].
123+ InputTokens int64 `json:"input_tokens"`
124+ // This field is from variant [TranscriptionUsageTokens].
125+ OutputTokens int64 `json:"output_tokens"`
126+ // This field is from variant [TranscriptionUsageTokens].
127+ TotalTokens int64 `json:"total_tokens"`
128+ // Any of "tokens", "duration".
129+ Type string `json:"type"`
130+ // This field is from variant [TranscriptionUsageTokens].
131+ InputTokenDetails TranscriptionUsageTokensInputTokenDetails `json:"input_token_details"`
132+ // This field is from variant [TranscriptionUsageDuration].
133+ Duration float64 `json:"duration"`
134+ JSON struct {
135+ InputTokens respjson.Field
136+ OutputTokens respjson.Field
137+ TotalTokens respjson.Field
138+ Type respjson.Field
139+ InputTokenDetails respjson.Field
140+ Duration respjson.Field
141+ raw string
142+ } `json:"-"`
143+}
144+
145+// anyTranscriptionUsage is implemented by each variant of
146+// [TranscriptionUsageUnion] to add type safety for the return type of
147+// [TranscriptionUsageUnion.AsAny]
148+type anyTranscriptionUsage interface {
149+ implTranscriptionUsageUnion()
150+}
151+
152+func (TranscriptionUsageTokens) implTranscriptionUsageUnion() {}
153+func (TranscriptionUsageDuration) implTranscriptionUsageUnion() {}
154+
155+// Use the following switch statement to find the correct variant
156+//
157+// switch variant := TranscriptionUsageUnion.AsAny().(type) {
158+// case openai.TranscriptionUsageTokens:
159+// case openai.TranscriptionUsageDuration:
160+// default:
161+// fmt.Errorf("no variant present")
162+// }
163+func (u TranscriptionUsageUnion) AsAny() anyTranscriptionUsage {
164+ switch u.Type {
165+ case "tokens":
166+ return u.AsTokens()
167+ case "duration":
168+ return u.AsDuration()
169+ }
170+ return nil
171+}
172+
173+func (u TranscriptionUsageUnion) AsTokens() (v TranscriptionUsageTokens) {
174+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
175+ return
176+}
177+
178+func (u TranscriptionUsageUnion) AsDuration() (v TranscriptionUsageDuration) {
179+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
180+ return
181+}
182+
183+// Returns the unmodified JSON received from the API
184+func (u TranscriptionUsageUnion) RawJSON() string { return u.JSON.raw }
185+
186+func (r *TranscriptionUsageUnion) UnmarshalJSON(data []byte) error {
187+ return apijson.UnmarshalRoot(data, r)
188+}
189+
190+// Usage statistics for models billed by token usage.
191+type TranscriptionUsageTokens struct {
192+ // Number of input tokens billed for this request.
193+ InputTokens int64 `json:"input_tokens,required"`
194+ // Number of output tokens generated.
195+ OutputTokens int64 `json:"output_tokens,required"`
196+ // Total number of tokens used (input + output).
197+ TotalTokens int64 `json:"total_tokens,required"`
198+ // The type of the usage object. Always `tokens` for this variant.
199+ Type constant.Tokens `json:"type,required"`
200+ // Details about the input tokens billed for this request.
201+ InputTokenDetails TranscriptionUsageTokensInputTokenDetails `json:"input_token_details"`
202+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
203+ JSON struct {
204+ InputTokens respjson.Field
205+ OutputTokens respjson.Field
206+ TotalTokens respjson.Field
207+ Type respjson.Field
208+ InputTokenDetails respjson.Field
209+ ExtraFields map[string]respjson.Field
210+ raw string
211+ } `json:"-"`
212+}
213+
214+// Returns the unmodified JSON received from the API
215+func (r TranscriptionUsageTokens) RawJSON() string { return r.JSON.raw }
216+func (r *TranscriptionUsageTokens) UnmarshalJSON(data []byte) error {
217+ return apijson.UnmarshalRoot(data, r)
218+}
219+
220+// Details about the input tokens billed for this request.
221+type TranscriptionUsageTokensInputTokenDetails struct {
222+ // Number of audio tokens billed for this request.
223+ AudioTokens int64 `json:"audio_tokens"`
224+ // Number of text tokens billed for this request.
225+ TextTokens int64 `json:"text_tokens"`
226+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
227+ JSON struct {
228+ AudioTokens respjson.Field
229+ TextTokens respjson.Field
230+ ExtraFields map[string]respjson.Field
231+ raw string
232+ } `json:"-"`
233+}
234+
235+// Returns the unmodified JSON received from the API
236+func (r TranscriptionUsageTokensInputTokenDetails) RawJSON() string { return r.JSON.raw }
237+func (r *TranscriptionUsageTokensInputTokenDetails) UnmarshalJSON(data []byte) error {
238+ return apijson.UnmarshalRoot(data, r)
239+}
240+
241+// Usage statistics for models billed by audio input duration.
242+type TranscriptionUsageDuration struct {
243+ // Duration of the input audio in seconds.
244+ Duration float64 `json:"duration,required"`
245+ // The type of the usage object. Always `duration` for this variant.
246+ Type constant.Duration `json:"type,required"`
247+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
248+ JSON struct {
249+ Duration respjson.Field
250+ Type respjson.Field
251+ ExtraFields map[string]respjson.Field
252+ raw string
253+ } `json:"-"`
254+}
255+
256+// Returns the unmodified JSON received from the API
257+func (r TranscriptionUsageDuration) RawJSON() string { return r.JSON.raw }
258+func (r *TranscriptionUsageDuration) UnmarshalJSON(data []byte) error {
259+ return apijson.UnmarshalRoot(data, r)
260+}
261+
112type TranscriptionInclude string
262type TranscriptionInclude string
113
263
114const (
264const (
@@ -131,24 +281,37 @@ type TranscriptionStreamEventUnion struct {
131 Logprobs TranscriptionStreamEventUnionLogprobs `json:"logprobs"`
281 Logprobs TranscriptionStreamEventUnionLogprobs `json:"logprobs"`
132 // This field is from variant [TranscriptionTextDoneEvent].
282 // This field is from variant [TranscriptionTextDoneEvent].
133 Text string `json:"text"`
283 Text string `json:"text"`
284+ // This field is from variant [TranscriptionTextDoneEvent].
285+ Usage TranscriptionTextDoneEventUsage `json:"usage"`
134− JSON struct {
286+ JSON struct {
135− Delta resp.Field
287+ Delta respjson.Field
136− Type resp.Field
288+ Type respjson.Field
137− Logprobs resp.Field
289+ Logprobs respjson.Field
138− Text resp.Field
290+ Text respjson.Field
291+ Usage respjson.Field
139 raw string
292 raw string
140 } `json:"-"`
293 } `json:"-"`
141}
294}
142
295
296+// anyTranscriptionStreamEvent is implemented by each variant of
297+// [TranscriptionStreamEventUnion] to add type safety for the return type of
298+// [TranscriptionStreamEventUnion.AsAny]
299+type anyTranscriptionStreamEvent interface {
300+ implTranscriptionStreamEventUnion()
301+}
302+
303+func (TranscriptionTextDeltaEvent) implTranscriptionStreamEventUnion() {}
304+func (TranscriptionTextDoneEvent) implTranscriptionStreamEventUnion() {}
305+
143// Use the following switch statement to find the correct variant
306// Use the following switch statement to find the correct variant
144//
307//
145// switch variant := TranscriptionStreamEventUnion.AsAny().(type) {
308// switch variant := TranscriptionStreamEventUnion.AsAny().(type) {
146−// case TranscriptionTextDeltaEvent:
309+// case openai.TranscriptionTextDeltaEvent:
147−// case TranscriptionTextDoneEvent:
310+// case openai.TranscriptionTextDoneEvent:
148// default:
311// default:
149// fmt.Errorf("no variant present")
312// fmt.Errorf("no variant present")
150// }
313// }
151−func (u TranscriptionStreamEventUnion) AsAny() any {
314+func (u TranscriptionStreamEventUnion) AsAny() anyTranscriptionStreamEvent {
152 switch u.Type {
315 switch u.Type {
153 case "transcript.text.delta":
316 case "transcript.text.delta":
154 return u.AsTranscriptTextDelta()
317 return u.AsTranscriptTextDelta()
@@ -193,8 +356,8 @@ type TranscriptionStreamEventUnionLogprobs struct {
193 // [[]TranscriptionTextDoneEventLogprob] instead of an object.
356 // [[]TranscriptionTextDoneEventLogprob] instead of an object.
194 OfTranscriptionTextDoneEventLogprobs []TranscriptionTextDoneEventLogprob `json:",inline"`
357 OfTranscriptionTextDoneEventLogprobs []TranscriptionTextDoneEventLogprob `json:",inline"`
195 JSON struct {
358 JSON struct {
196− OfTranscriptionTextDeltaEventLogprobs resp.Field
359+ OfTranscriptionTextDeltaEventLogprobs respjson.Field
197− OfTranscriptionTextDoneEventLogprobs resp.Field
360+ OfTranscriptionTextDoneEventLogprobs respjson.Field
198 raw string
361 raw string
199 } `json:"-"`
362 } `json:"-"`
200}
363}
@@ -216,13 +379,12 @@ type TranscriptionTextDeltaEvent struct {
216 // [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription)
379 // [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription)
217 // with the `include[]` parameter set to `logprobs`.
380 // with the `include[]` parameter set to `logprobs`.
218 Logprobs []TranscriptionTextDeltaEventLogprob `json:"logprobs"`
381 Logprobs []TranscriptionTextDeltaEventLogprob `json:"logprobs"`
219− // Metadata for the response, check the presence of optional fields with the
382+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
220− // [resp.Field.IsPresent] method.
221 JSON struct {
383 JSON struct {
222− Delta resp.Field
384+ Delta respjson.Field
223− Type resp.Field
385+ Type respjson.Field
224− Logprobs resp.Field
386+ Logprobs respjson.Field
225− ExtraFields map[string]resp.Field
387+ ExtraFields map[string]respjson.Field
226 raw string
388 raw string
227 } `json:"-"`
389 } `json:"-"`
228}
390}
@@ -237,16 +399,15 @@ type TranscriptionTextDeltaEventLogprob struct {
237 // The token that was used to generate the log probability.
399 // The token that was used to generate the log probability.
238 Token string `json:"token"`
400 Token string `json:"token"`
239 // The bytes that were used to generate the log probability.
401 // The bytes that were used to generate the log probability.
240− Bytes []interface{} `json:"bytes"`
402+ Bytes []int64 `json:"bytes"`
241 // The log probability of the token.
403 // The log probability of the token.
242 Logprob float64 `json:"logprob"`
404 Logprob float64 `json:"logprob"`
243− // Metadata for the response, check the presence of optional fields with the
405+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
244− // [resp.Field.IsPresent] method.
245 JSON struct {
406 JSON struct {
246− Token resp.Field
407+ Token respjson.Field
247− Bytes resp.Field
408+ Bytes respjson.Field
248− Logprob resp.Field
409+ Logprob respjson.Field
249− ExtraFields map[string]resp.Field
410+ ExtraFields map[string]respjson.Field
250 raw string
411 raw string
251 } `json:"-"`
412 } `json:"-"`
252}
413}
@@ -271,13 +432,15 @@ type TranscriptionTextDoneEvent struct {
271 // [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription)
432 // [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription)
272 // with the `include[]` parameter set to `logprobs`.
433 // with the `include[]` parameter set to `logprobs`.
273 Logprobs []TranscriptionTextDoneEventLogprob `json:"logprobs"`
434 Logprobs []TranscriptionTextDoneEventLogprob `json:"logprobs"`
274− // Metadata for the response, check the presence of optional fields with the
435+ // Usage statistics for models billed by token usage.
275− // [resp.Field.IsPresent] method.
436+ Usage TranscriptionTextDoneEventUsage `json:"usage"`
437+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
276 JSON struct {
438 JSON struct {
277− Text resp.Field
439+ Text respjson.Field
278− Type resp.Field
440+ Type respjson.Field
279− Logprobs resp.Field
441+ Logprobs respjson.Field
442+ Usage respjson.Field
280− ExtraFields map[string]resp.Field
443+ ExtraFields map[string]respjson.Field
281 raw string
444 raw string
282 } `json:"-"`
445 } `json:"-"`
283}
446}
@@ -292,16 +455,15 @@ type TranscriptionTextDoneEventLogprob struct {
292 // The token that was used to generate the log probability.
455 // The token that was used to generate the log probability.
293 Token string `json:"token"`
456 Token string `json:"token"`
294 // The bytes that were used to generate the log probability.
457 // The bytes that were used to generate the log probability.
295− Bytes []interface{} `json:"bytes"`
458+ Bytes []int64 `json:"bytes"`
296 // The log probability of the token.
459 // The log probability of the token.
297 Logprob float64 `json:"logprob"`
460 Logprob float64 `json:"logprob"`
298− // Metadata for the response, check the presence of optional fields with the
461+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
299− // [resp.Field.IsPresent] method.
300 JSON struct {
462 JSON struct {
301− Token resp.Field
463+ Token respjson.Field
302− Bytes resp.Field
464+ Bytes respjson.Field
303− Logprob resp.Field
465+ Logprob respjson.Field
304− ExtraFields map[string]resp.Field
466+ ExtraFields map[string]respjson.Field
305 raw string
467 raw string
306 } `json:"-"`
468 } `json:"-"`
307}
469}
@@ -312,10 +474,61 @@ func (r *TranscriptionTextDoneEventLogprob) UnmarshalJSON(data []byte) error {
312 return apijson.UnmarshalRoot(data, r)
474 return apijson.UnmarshalRoot(data, r)
313}
475}
314
476
477+// Usage statistics for models billed by token usage.
478+type TranscriptionTextDoneEventUsage struct {
479+ // Number of input tokens billed for this request.
480+ InputTokens int64 `json:"input_tokens,required"`
481+ // Number of output tokens generated.
482+ OutputTokens int64 `json:"output_tokens,required"`
483+ // Total number of tokens used (input + output).
484+ TotalTokens int64 `json:"total_tokens,required"`
485+ // The type of the usage object. Always `tokens` for this variant.
486+ Type constant.Tokens `json:"type,required"`
487+ // Details about the input tokens billed for this request.
488+ InputTokenDetails TranscriptionTextDoneEventUsageInputTokenDetails `json:"input_token_details"`
489+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
490+ JSON struct {
491+ InputTokens respjson.Field
492+ OutputTokens respjson.Field
493+ TotalTokens respjson.Field
494+ Type respjson.Field
495+ InputTokenDetails respjson.Field
496+ ExtraFields map[string]respjson.Field
497+ raw string
498+ } `json:"-"`
499+}
500+
501+// Returns the unmodified JSON received from the API
502+func (r TranscriptionTextDoneEventUsage) RawJSON() string { return r.JSON.raw }
503+func (r *TranscriptionTextDoneEventUsage) UnmarshalJSON(data []byte) error {
504+ return apijson.UnmarshalRoot(data, r)
505+}
506+
507+// Details about the input tokens billed for this request.
508+type TranscriptionTextDoneEventUsageInputTokenDetails struct {
509+ // Number of audio tokens billed for this request.
510+ AudioTokens int64 `json:"audio_tokens"`
511+ // Number of text tokens billed for this request.
512+ TextTokens int64 `json:"text_tokens"`
513+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
514+ JSON struct {
515+ AudioTokens respjson.Field
516+ TextTokens respjson.Field
517+ ExtraFields map[string]respjson.Field
518+ raw string
519+ } `json:"-"`
520+}
521+
522+// Returns the unmodified JSON received from the API
523+func (r TranscriptionTextDoneEventUsageInputTokenDetails) RawJSON() string { return r.JSON.raw }
524+func (r *TranscriptionTextDoneEventUsageInputTokenDetails) UnmarshalJSON(data []byte) error {
525+ return apijson.UnmarshalRoot(data, r)
526+}
527+
315type AudioTranscriptionNewParams struct {
528type AudioTranscriptionNewParams struct {
316 // The audio file object (not file name) to transcribe, in one of these formats:
529 // The audio file object (not file name) to transcribe, in one of these formats:
317 // flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.
530 // flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.
318− File io.Reader `json:"file,required" format:"binary"`
531+ File io.Reader `json:"file,omitzero,required" format:"binary"`
319 // ID of the model to use. The options are `gpt-4o-transcribe`,
532 // ID of the model to use. The options are `gpt-4o-transcribe`,
320 // `gpt-4o-mini-transcribe`, and `whisper-1` (which is powered by our open source
533 // `gpt-4o-mini-transcribe`, and `whisper-1` (which is powered by our open source
321 // Whisper V2 model).
534 // Whisper V2 model).
@@ -335,6 +548,11 @@ type AudioTranscriptionNewParams struct {
335 // [log probability](https://en.wikipedia.org/wiki/Log_probability) to
548 // [log probability](https://en.wikipedia.org/wiki/Log_probability) to
336 // automatically increase the temperature until certain thresholds are hit.
549 // automatically increase the temperature until certain thresholds are hit.
337 Temperature param.Opt[float64] `json:"temperature,omitzero"`
550 Temperature param.Opt[float64] `json:"temperature,omitzero"`
551+ // Controls how the audio is cut into chunks. When set to `"auto"`, the server
552+ // first normalizes loudness and then uses voice activity detection (VAD) to choose
553+ // boundaries. `server_vad` object can be provided to tweak VAD detection
554+ // parameters manually. If unset, the audio is transcribed as a single block.
555+ ChunkingStrategy AudioTranscriptionNewParamsChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
338 // Additional information to include in the transcription response. `logprobs` will
556 // Additional information to include in the transcription response. `logprobs` will
339 // return the log probabilities of the tokens in the response to understand the
557 // return the log probabilities of the tokens in the response to understand the
340 // model's confidence in the transcription. `logprobs` only works with
558 // model's confidence in the transcription. `logprobs` only works with
@@ -352,18 +570,19 @@ type AudioTranscriptionNewParams struct {
352 // Either or both of these options are supported: `word`, or `segment`. Note: There
570 // Either or both of these options are supported: `word`, or `segment`. Note: There
353 // is no additional latency for segment timestamps, but generating word timestamps
571 // is no additional latency for segment timestamps, but generating word timestamps
354 // incurs additional latency.
572 // incurs additional latency.
573+ //
574+ // Any of "word", "segment".
355 TimestampGranularities []string `json:"timestamp_granularities,omitzero"`
575 TimestampGranularities []string `json:"timestamp_granularities,omitzero"`
356 paramObj
576 paramObj
357}
577}
358
578
359−// IsPresent returns true if the field's value is not omitted and not the JSON
360−// "null". To check if this field is omitted, use [param.IsOmitted].
361−func (f AudioTranscriptionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
362−
363func (r AudioTranscriptionNewParams) MarshalMultipart() (data []byte, contentType string, err error) {
579func (r AudioTranscriptionNewParams) MarshalMultipart() (data []byte, contentType string, err error) {
364 buf := bytes.NewBuffer(nil)
580 buf := bytes.NewBuffer(nil)
365 writer := multipart.NewWriter(buf)
581 writer := multipart.NewWriter(buf)
366 err = apiform.MarshalRoot(r, writer)
582 err = apiform.MarshalRoot(r, writer)
583+ if err == nil {
584+ err = apiform.WriteExtras(writer, r.ExtraFields())
585+ }
367 if err != nil {
586 if err != nil {
368 writer.Close()
587 writer.Close()
369 return nil, "", err
588 return nil, "", err
@@ -374,3 +593,62 @@ func (r AudioTranscriptionNewParams) MarshalMultipart() (data []byte, contentTyp
374 }
593 }
375 return buf.Bytes(), writer.FormDataContentType(), nil
594 return buf.Bytes(), writer.FormDataContentType(), nil
376}
595}
596+
597+// Only one field can be non-zero.
598+//
599+// Use [param.IsOmitted] to confirm if a field is set.
600+type AudioTranscriptionNewParamsChunkingStrategyUnion struct {
601+ // Construct this variant with constant.ValueOf[constant.Auto]()
602+ OfAuto constant.Auto `json:",omitzero,inline"`
603+ OfAudioTranscriptionNewsChunkingStrategyVadConfig *AudioTranscriptionNewParamsChunkingStrategyVadConfig `json:",omitzero,inline"`
604+ paramUnion
605+}
606+
607+func (u AudioTranscriptionNewParamsChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
608+ return param.MarshalUnion(u, u.OfAuto, u.OfAudioTranscriptionNewsChunkingStrategyVadConfig)
609+}
610+func (u *AudioTranscriptionNewParamsChunkingStrategyUnion) UnmarshalJSON(data []byte) error {
611+ return apijson.UnmarshalRoot(data, u)
612+}
613+
614+func (u *AudioTranscriptionNewParamsChunkingStrategyUnion) asAny() any {
615+ if !param.IsOmitted(u.OfAuto) {
616+ return &u.OfAuto
617+ } else if !param.IsOmitted(u.OfAudioTranscriptionNewsChunkingStrategyVadConfig) {
618+ return u.OfAudioTranscriptionNewsChunkingStrategyVadConfig
619+ }
620+ return nil
621+}
622+
623+// The property Type is required.
624+type AudioTranscriptionNewParamsChunkingStrategyVadConfig struct {
625+ // Must be set to `server_vad` to enable manual chunking using server side VAD.
626+ //
627+ // Any of "server_vad".
628+ Type string `json:"type,omitzero,required"`
629+ // Amount of audio to include before the VAD detected speech (in milliseconds).
630+ PrefixPaddingMs param.Opt[int64] `json:"prefix_padding_ms,omitzero"`
631+ // Duration of silence to detect speech stop (in milliseconds). With shorter values
632+ // the model will respond more quickly, but may jump in on short pauses from the
633+ // user.
634+ SilenceDurationMs param.Opt[int64] `json:"silence_duration_ms,omitzero"`
635+ // Sensitivity threshold (0.0 to 1.0) for voice activity detection. A higher
636+ // threshold will require louder audio to activate the model, and thus might
637+ // perform better in noisy environments.
638+ Threshold param.Opt[float64] `json:"threshold,omitzero"`
639+ paramObj
640+}
641+
642+func (r AudioTranscriptionNewParamsChunkingStrategyVadConfig) MarshalJSON() (data []byte, err error) {
643+ type shadow AudioTranscriptionNewParamsChunkingStrategyVadConfig
644+ return param.MarshalObject(r, (*shadow)(&r))
645+}
646+func (r *AudioTranscriptionNewParamsChunkingStrategyVadConfig) UnmarshalJSON(data []byte) error {
647+ return apijson.UnmarshalRoot(data, r)
648+}
649+
650+func init() {
651+ apijson.RegisterFieldValidator[AudioTranscriptionNewParamsChunkingStrategyVadConfig](
652+ "type", "server_vad",
653+ )
654+}
vendor/github.com/openai/openai-go/audiotranslation.go+8−10
@@ -14,7 +14,7 @@ import (
14 "github.com/openai/openai-go/internal/requestconfig"
14 "github.com/openai/openai-go/internal/requestconfig"
15 "github.com/openai/openai-go/option"
15 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/packages/param"
16 "github.com/openai/openai-go/packages/param"
17− "github.com/openai/openai-go/packages/resp"
17+ "github.com/openai/openai-go/packages/respjson"
18)
18)
19
19
20// AudioTranslationService contains methods and other services that help with
20// AudioTranslationService contains methods and other services that help with
@@ -46,11 +46,10 @@ func (r *AudioTranslationService) New(ctx context.Context, body AudioTranslation
46
46
47type Translation struct {
47type Translation struct {
48 Text string `json:"text,required"`
48 Text string `json:"text,required"`
49− // Metadata for the response, check the presence of optional fields with the
49+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
50− // [resp.Field.IsPresent] method.
51 JSON struct {
50 JSON struct {
52− Text resp.Field
51+ Text respjson.Field
53− ExtraFields map[string]resp.Field
52+ ExtraFields map[string]respjson.Field
54 raw string
53 raw string
55 } `json:"-"`
54 } `json:"-"`
56}
55}
@@ -64,7 +63,7 @@ func (r *Translation) UnmarshalJSON(data []byte) error {
64type AudioTranslationNewParams struct {
63type AudioTranslationNewParams struct {
65 // The audio file object (not file name) translate, in one of these formats: flac,
64 // The audio file object (not file name) translate, in one of these formats: flac,
66 // mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.
65 // mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.
67− File io.Reader `json:"file,required" format:"binary"`
66+ File io.Reader `json:"file,omitzero,required" format:"binary"`
68 // ID of the model to use. Only `whisper-1` (which is powered by our open source
67 // ID of the model to use. Only `whisper-1` (which is powered by our open source
69 // Whisper V2 model) is currently available.
68 // Whisper V2 model) is currently available.
70 Model AudioModel `json:"model,omitzero,required"`
69 Model AudioModel `json:"model,omitzero,required"`
@@ -87,14 +86,13 @@ type AudioTranslationNewParams struct {
87 paramObj
86 paramObj
88}
87}
89
88
90−// IsPresent returns true if the field's value is not omitted and not the JSON
91−// "null". To check if this field is omitted, use [param.IsOmitted].
92−func (f AudioTranslationNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
93−
94func (r AudioTranslationNewParams) MarshalMultipart() (data []byte, contentType string, err error) {
89func (r AudioTranslationNewParams) MarshalMultipart() (data []byte, contentType string, err error) {
95 buf := bytes.NewBuffer(nil)
90 buf := bytes.NewBuffer(nil)
96 writer := multipart.NewWriter(buf)
91 writer := multipart.NewWriter(buf)
97 err = apiform.MarshalRoot(r, writer)
92 err = apiform.MarshalRoot(r, writer)
93+ if err == nil {
94+ err = apiform.WriteExtras(writer, r.ExtraFields())
95+ }
98 if err != nil {
96 if err != nil {
99 writer.Close()
97 writer.Close()
100 return nil, "", err
98 return nil, "", err
vendor/github.com/openai/openai-go/batch.go+43−52
@@ -15,7 +15,7 @@ import (
15 "github.com/openai/openai-go/option"
15 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/packages/pagination"
16 "github.com/openai/openai-go/packages/pagination"
17 "github.com/openai/openai-go/packages/param"
17 "github.com/openai/openai-go/packages/param"
18− "github.com/openai/openai-go/packages/resp"
18+ "github.com/openai/openai-go/packages/respjson"
19 "github.com/openai/openai-go/shared"
19 "github.com/openai/openai-go/shared"
20 "github.com/openai/openai-go/shared/constant"
20 "github.com/openai/openai-go/shared/constant"
21)
21)
@@ -143,30 +143,29 @@ type Batch struct {
143 OutputFileID string `json:"output_file_id"`
143 OutputFileID string `json:"output_file_id"`
144 // The request counts for different statuses within the batch.
144 // The request counts for different statuses within the batch.
145 RequestCounts BatchRequestCounts `json:"request_counts"`
145 RequestCounts BatchRequestCounts `json:"request_counts"`
146− // Metadata for the response, check the presence of optional fields with the
146+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
147− // [resp.Field.IsPresent] method.
148 JSON struct {
147 JSON struct {
149− ID resp.Field
148+ ID respjson.Field
150− CompletionWindow resp.Field
149+ CompletionWindow respjson.Field
151− CreatedAt resp.Field
150+ CreatedAt respjson.Field
152− Endpoint resp.Field
151+ Endpoint respjson.Field
153− InputFileID resp.Field
152+ InputFileID respjson.Field
154− Object resp.Field
153+ Object respjson.Field
155− Status resp.Field
154+ Status respjson.Field
156− CancelledAt resp.Field
155+ CancelledAt respjson.Field
157− CancellingAt resp.Field
156+ CancellingAt respjson.Field
158− CompletedAt resp.Field
157+ CompletedAt respjson.Field
159− ErrorFileID resp.Field
158+ ErrorFileID respjson.Field
160− Errors resp.Field
159+ Errors respjson.Field
161− ExpiredAt resp.Field
160+ ExpiredAt respjson.Field
162− ExpiresAt resp.Field
161+ ExpiresAt respjson.Field
163− FailedAt resp.Field
162+ FailedAt respjson.Field
164− FinalizingAt resp.Field
163+ FinalizingAt respjson.Field
165− InProgressAt resp.Field
164+ InProgressAt respjson.Field
166− Metadata resp.Field
165+ Metadata respjson.Field
167− OutputFileID resp.Field
166+ OutputFileID respjson.Field
168− RequestCounts resp.Field
167+ RequestCounts respjson.Field
169− ExtraFields map[string]resp.Field
168+ ExtraFields map[string]respjson.Field
170 raw string
169 raw string
171 } `json:"-"`
170 } `json:"-"`
172}
171}
@@ -195,12 +194,11 @@ type BatchErrors struct {
195 Data []BatchError `json:"data"`
194 Data []BatchError `json:"data"`
196 // The object type, which is always `list`.
195 // The object type, which is always `list`.
197 Object string `json:"object"`
196 Object string `json:"object"`
198− // Metadata for the response, check the presence of optional fields with the
197+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
199− // [resp.Field.IsPresent] method.
200 JSON struct {
198 JSON struct {
201− Data resp.Field
199+ Data respjson.Field
202− Object resp.Field
200+ Object respjson.Field
203− ExtraFields map[string]resp.Field
201+ ExtraFields map[string]respjson.Field
204 raw string
202 raw string
205 } `json:"-"`
203 } `json:"-"`
206}
204}
@@ -220,14 +218,13 @@ type BatchError struct {
220 Message string `json:"message"`
218 Message string `json:"message"`
221 // The name of the parameter that caused the error, if applicable.
219 // The name of the parameter that caused the error, if applicable.
222 Param string `json:"param,nullable"`
220 Param string `json:"param,nullable"`
223− // Metadata for the response, check the presence of optional fields with the
221+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
224− // [resp.Field.IsPresent] method.
225 JSON struct {
222 JSON struct {
226− Code resp.Field
223+ Code respjson.Field
227− Line resp.Field
224+ Line respjson.Field
228− Message resp.Field
225+ Message respjson.Field
229− Param resp.Field
226+ Param respjson.Field
230− ExtraFields map[string]resp.Field
227+ ExtraFields map[string]respjson.Field
231 raw string
228 raw string
232 } `json:"-"`
229 } `json:"-"`
233}
230}
@@ -246,13 +243,12 @@ type BatchRequestCounts struct {
246 Failed int64 `json:"failed,required"`
243 Failed int64 `json:"failed,required"`
247 // Total number of requests in the batch.
244 // Total number of requests in the batch.
248 Total int64 `json:"total,required"`
245 Total int64 `json:"total,required"`
249− // Metadata for the response, check the presence of optional fields with the
246+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
250− // [resp.Field.IsPresent] method.
251 JSON struct {
247 JSON struct {
252− Completed resp.Field
248+ Completed respjson.Field
253− Failed resp.Field
249+ Failed respjson.Field
254− Total resp.Field
250+ Total respjson.Field
255− ExtraFields map[string]resp.Field
251+ ExtraFields map[string]respjson.Field
256 raw string
252 raw string
257 } `json:"-"`
253 } `json:"-"`
258}
254}
@@ -293,18 +289,17 @@ type BatchNewParams struct {
293 //
289 //
294 // Keys are strings with a maximum length of 64 characters. Values are strings with
290 // Keys are strings with a maximum length of 64 characters. Values are strings with
295 // a maximum length of 512 characters.
291 // a maximum length of 512 characters.
296− Metadata shared.MetadataParam `json:"metadata,omitzero"`
292+ Metadata shared.Metadata `json:"metadata,omitzero"`
297 paramObj
293 paramObj
298}
294}
299
295
300−// IsPresent returns true if the field's value is not omitted and not the JSON
301−// "null". To check if this field is omitted, use [param.IsOmitted].
302−func (f BatchNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
303−
304func (r BatchNewParams) MarshalJSON() (data []byte, err error) {
296func (r BatchNewParams) MarshalJSON() (data []byte, err error) {
305 type shadow BatchNewParams
297 type shadow BatchNewParams
306 return param.MarshalObject(r, (*shadow)(&r))
298 return param.MarshalObject(r, (*shadow)(&r))
307}
299}
300+func (r *BatchNewParams) UnmarshalJSON(data []byte) error {
301+ return apijson.UnmarshalRoot(data, r)
302+}
308
303
309// The time frame within which the batch should be processed. Currently only `24h`
304// The time frame within which the batch should be processed. Currently only `24h`
310// is supported.
305// is supported.
@@ -339,12 +334,8 @@ type BatchListParams struct {
339 paramObj
334 paramObj
340}
335}
341
336
342−// IsPresent returns true if the field's value is not omitted and not the JSON
343−// "null". To check if this field is omitted, use [param.IsOmitted].
344−func (f BatchListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
345−
346// URLQuery serializes [BatchListParams]'s query parameters as `url.Values`.
337// URLQuery serializes [BatchListParams]'s query parameters as `url.Values`.
347−func (r BatchListParams) URLQuery() (v url.Values) {
338+func (r BatchListParams) URLQuery() (v url.Values, err error) {
348 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
339 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
349 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
340 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
350 NestedFormat: apiquery.NestedQueryFormatBrackets,
341 NestedFormat: apiquery.NestedQueryFormatBrackets,
vendor/github.com/openai/openai-go/beta.go+2−1
@@ -15,7 +15,8 @@ import (
15type BetaService struct {
15type BetaService struct {
16 Options []option.RequestOption
16 Options []option.RequestOption
17 Assistants BetaAssistantService
17 Assistants BetaAssistantService
18+ // Deprecated: The Assistants API is deprecated in favor of the Responses API
18− Threads BetaThreadService
19+ Threads BetaThreadService
19}
20}
20
21
21// NewBetaService generates a new service that applies the given options to each
22// NewBetaService generates a new service that applies the given options to each
vendor/github.com/openai/openai-go/betaassistant.go+413−401
@@ -9,7 +9,6 @@ import (
9 "fmt"
9 "fmt"
10 "net/http"
10 "net/http"
11 "net/url"
11 "net/url"
12− "reflect"
13
12
14 "github.com/openai/openai-go/internal/apijson"
13 "github.com/openai/openai-go/internal/apijson"
15 "github.com/openai/openai-go/internal/apiquery"
14 "github.com/openai/openai-go/internal/apiquery"
@@ -17,10 +16,9 @@ import (
17 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/option"
18 "github.com/openai/openai-go/packages/pagination"
17 "github.com/openai/openai-go/packages/pagination"
19 "github.com/openai/openai-go/packages/param"
18 "github.com/openai/openai-go/packages/param"
20− "github.com/openai/openai-go/packages/resp"
19+ "github.com/openai/openai-go/packages/respjson"
21 "github.com/openai/openai-go/shared"
20 "github.com/openai/openai-go/shared"
22 "github.com/openai/openai-go/shared/constant"
21 "github.com/openai/openai-go/shared/constant"
23− "github.com/tidwall/gjson"
24)
22)
25
23
26// BetaAssistantService contains methods and other services that help with
24// BetaAssistantService contains methods and other services that help with
@@ -181,23 +179,22 @@ type Assistant struct {
181 //
179 //
182 // We generally recommend altering this or temperature but not both.
180 // We generally recommend altering this or temperature but not both.
183 TopP float64 `json:"top_p,nullable"`
181 TopP float64 `json:"top_p,nullable"`
184− // Metadata for the response, check the presence of optional fields with the
182+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
185− // [resp.Field.IsPresent] method.
186 JSON struct {
183 JSON struct {
187− ID resp.Field
184+ ID respjson.Field
188− CreatedAt resp.Field
185+ CreatedAt respjson.Field
189− Description resp.Field
186+ Description respjson.Field
190− Instructions resp.Field
187+ Instructions respjson.Field
191− Metadata resp.Field
188+ Metadata respjson.Field
192− Model resp.Field
189+ Model respjson.Field
193− Name resp.Field
190+ Name respjson.Field
194− Object resp.Field
191+ Object respjson.Field
195− Tools resp.Field
192+ Tools respjson.Field
196− ResponseFormat resp.Field
193+ ResponseFormat respjson.Field
197− Temperature resp.Field
194+ Temperature respjson.Field
198− ToolResources resp.Field
195+ ToolResources respjson.Field
199− TopP resp.Field
196+ TopP respjson.Field
200− ExtraFields map[string]resp.Field
197+ ExtraFields map[string]respjson.Field
201 raw string
198 raw string
202 } `json:"-"`
199 } `json:"-"`
203}
200}
@@ -215,12 +212,11 @@ func (r *Assistant) UnmarshalJSON(data []byte) error {
215type AssistantToolResources struct {
212type AssistantToolResources struct {
216 CodeInterpreter AssistantToolResourcesCodeInterpreter `json:"code_interpreter"`
213 CodeInterpreter AssistantToolResourcesCodeInterpreter `json:"code_interpreter"`
217 FileSearch AssistantToolResourcesFileSearch `json:"file_search"`
214 FileSearch AssistantToolResourcesFileSearch `json:"file_search"`
218− // Metadata for the response, check the presence of optional fields with the
215+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
219− // [resp.Field.IsPresent] method.
220 JSON struct {
216 JSON struct {
221− CodeInterpreter resp.Field
217+ CodeInterpreter respjson.Field
222− FileSearch resp.Field
218+ FileSearch respjson.Field
223− ExtraFields map[string]resp.Field
219+ ExtraFields map[string]respjson.Field
224 raw string
220 raw string
225 } `json:"-"`
221 } `json:"-"`
226}
222}
@@ -236,11 +232,10 @@ type AssistantToolResourcesCodeInterpreter struct {
236 // available to the `code_interpreter“ tool. There can be a maximum of 20 files
232 // available to the `code_interpreter“ tool. There can be a maximum of 20 files
237 // associated with the tool.
233 // associated with the tool.
238 FileIDs []string `json:"file_ids"`
234 FileIDs []string `json:"file_ids"`
239− // Metadata for the response, check the presence of optional fields with the
235+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
240− // [resp.Field.IsPresent] method.
241 JSON struct {
236 JSON struct {
242− FileIDs resp.Field
237+ FileIDs respjson.Field
243− ExtraFields map[string]resp.Field
238+ ExtraFields map[string]respjson.Field
244 raw string
239 raw string
245 } `json:"-"`
240 } `json:"-"`
246}
241}
@@ -257,11 +252,10 @@ type AssistantToolResourcesFileSearch struct {
257 // attached to this assistant. There can be a maximum of 1 vector store attached to
252 // attached to this assistant. There can be a maximum of 1 vector store attached to
258 // the assistant.
253 // the assistant.
259 VectorStoreIDs []string `json:"vector_store_ids"`
254 VectorStoreIDs []string `json:"vector_store_ids"`
260− // Metadata for the response, check the presence of optional fields with the
255+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
261− // [resp.Field.IsPresent] method.
262 JSON struct {
256 JSON struct {
263− VectorStoreIDs resp.Field
257+ VectorStoreIDs respjson.Field
264− ExtraFields map[string]resp.Field
258+ ExtraFields map[string]respjson.Field
265 raw string
259 raw string
266 } `json:"-"`
260 } `json:"-"`
267}
261}
@@ -276,13 +270,12 @@ type AssistantDeleted struct {
276 ID string `json:"id,required"`
270 ID string `json:"id,required"`
277 Deleted bool `json:"deleted,required"`
271 Deleted bool `json:"deleted,required"`
278 Object constant.AssistantDeleted `json:"object,required"`
272 Object constant.AssistantDeleted `json:"object,required"`
279− // Metadata for the response, check the presence of optional fields with the
273+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
280− // [resp.Field.IsPresent] method.
281 JSON struct {
274 JSON struct {
282− ID resp.Field
275+ ID respjson.Field
283− Deleted resp.Field
276+ Deleted respjson.Field
284− Object resp.Field
277+ Object respjson.Field
285− ExtraFields map[string]resp.Field
278+ ExtraFields map[string]respjson.Field
286 raw string
279 raw string
287 } `json:"-"`
280 } `json:"-"`
288}
281}
@@ -337,44 +330,76 @@ type AssistantStreamEventUnion struct {
337 // This field is from variant [AssistantStreamEventThreadCreated].
330 // This field is from variant [AssistantStreamEventThreadCreated].
338 Enabled bool `json:"enabled"`
331 Enabled bool `json:"enabled"`
339 JSON struct {
332 JSON struct {
340− Data resp.Field
333+ Data respjson.Field
341− Event resp.Field
334+ Event respjson.Field
342− Enabled resp.Field
335+ Enabled respjson.Field
343 raw string
336 raw string
344 } `json:"-"`
337 } `json:"-"`
345}
338}
346
339
340+// anyAssistantStreamEvent is implemented by each variant of
341+// [AssistantStreamEventUnion] to add type safety for the return type of
342+// [AssistantStreamEventUnion.AsAny]
343+type anyAssistantStreamEvent interface {
344+ implAssistantStreamEventUnion()
345+}
346+
347+func (AssistantStreamEventThreadCreated) implAssistantStreamEventUnion() {}
348+func (AssistantStreamEventThreadRunCreated) implAssistantStreamEventUnion() {}
349+func (AssistantStreamEventThreadRunQueued) implAssistantStreamEventUnion() {}
350+func (AssistantStreamEventThreadRunInProgress) implAssistantStreamEventUnion() {}
351+func (AssistantStreamEventThreadRunRequiresAction) implAssistantStreamEventUnion() {}
352+func (AssistantStreamEventThreadRunCompleted) implAssistantStreamEventUnion() {}
353+func (AssistantStreamEventThreadRunIncomplete) implAssistantStreamEventUnion() {}
354+func (AssistantStreamEventThreadRunFailed) implAssistantStreamEventUnion() {}
355+func (AssistantStreamEventThreadRunCancelling) implAssistantStreamEventUnion() {}
356+func (AssistantStreamEventThreadRunCancelled) implAssistantStreamEventUnion() {}
357+func (AssistantStreamEventThreadRunExpired) implAssistantStreamEventUnion() {}
358+func (AssistantStreamEventThreadRunStepCreated) implAssistantStreamEventUnion() {}
359+func (AssistantStreamEventThreadRunStepInProgress) implAssistantStreamEventUnion() {}
360+func (AssistantStreamEventThreadRunStepDelta) implAssistantStreamEventUnion() {}
361+func (AssistantStreamEventThreadRunStepCompleted) implAssistantStreamEventUnion() {}
362+func (AssistantStreamEventThreadRunStepFailed) implAssistantStreamEventUnion() {}
363+func (AssistantStreamEventThreadRunStepCancelled) implAssistantStreamEventUnion() {}
364+func (AssistantStreamEventThreadRunStepExpired) implAssistantStreamEventUnion() {}
365+func (AssistantStreamEventThreadMessageCreated) implAssistantStreamEventUnion() {}
366+func (AssistantStreamEventThreadMessageInProgress) implAssistantStreamEventUnion() {}
367+func (AssistantStreamEventThreadMessageDelta) implAssistantStreamEventUnion() {}
368+func (AssistantStreamEventThreadMessageCompleted) implAssistantStreamEventUnion() {}
369+func (AssistantStreamEventThreadMessageIncomplete) implAssistantStreamEventUnion() {}
370+func (AssistantStreamEventErrorEvent) implAssistantStreamEventUnion() {}
371+
347// Use the following switch statement to find the correct variant
372// Use the following switch statement to find the correct variant
348//
373//
349// switch variant := AssistantStreamEventUnion.AsAny().(type) {
374// switch variant := AssistantStreamEventUnion.AsAny().(type) {
350−// case AssistantStreamEventThreadCreated:
375+// case openai.AssistantStreamEventThreadCreated:
351−// case AssistantStreamEventThreadRunCreated:
376+// case openai.AssistantStreamEventThreadRunCreated:
352−// case AssistantStreamEventThreadRunQueued:
377+// case openai.AssistantStreamEventThreadRunQueued:
353−// case AssistantStreamEventThreadRunInProgress:
378+// case openai.AssistantStreamEventThreadRunInProgress:
354−// case AssistantStreamEventThreadRunRequiresAction:
379+// case openai.AssistantStreamEventThreadRunRequiresAction:
355−// case AssistantStreamEventThreadRunCompleted:
380+// case openai.AssistantStreamEventThreadRunCompleted:
356−// case AssistantStreamEventThreadRunIncomplete:
381+// case openai.AssistantStreamEventThreadRunIncomplete:
357−// case AssistantStreamEventThreadRunFailed:
382+// case openai.AssistantStreamEventThreadRunFailed:
358−// case AssistantStreamEventThreadRunCancelling:
383+// case openai.AssistantStreamEventThreadRunCancelling:
359−// case AssistantStreamEventThreadRunCancelled:
384+// case openai.AssistantStreamEventThreadRunCancelled:
360−// case AssistantStreamEventThreadRunExpired:
385+// case openai.AssistantStreamEventThreadRunExpired:
361−// case AssistantStreamEventThreadRunStepCreated:
386+// case openai.AssistantStreamEventThreadRunStepCreated:
362−// case AssistantStreamEventThreadRunStepInProgress:
387+// case openai.AssistantStreamEventThreadRunStepInProgress:
363−// case AssistantStreamEventThreadRunStepDelta:
388+// case openai.AssistantStreamEventThreadRunStepDelta:
364−// case AssistantStreamEventThreadRunStepCompleted:
389+// case openai.AssistantStreamEventThreadRunStepCompleted:
365−// case AssistantStreamEventThreadRunStepFailed:
390+// case openai.AssistantStreamEventThreadRunStepFailed:
366−// case AssistantStreamEventThreadRunStepCancelled:
391+// case openai.AssistantStreamEventThreadRunStepCancelled:
367−// case AssistantStreamEventThreadRunStepExpired:
392+// case openai.AssistantStreamEventThreadRunStepExpired:
368−// case AssistantStreamEventThreadMessageCreated:
393+// case openai.AssistantStreamEventThreadMessageCreated:
369−// case AssistantStreamEventThreadMessageInProgress:
394+// case openai.AssistantStreamEventThreadMessageInProgress:
370−// case AssistantStreamEventThreadMessageDelta:
395+// case openai.AssistantStreamEventThreadMessageDelta:
371−// case AssistantStreamEventThreadMessageCompleted:
396+// case openai.AssistantStreamEventThreadMessageCompleted:
372−// case AssistantStreamEventThreadMessageIncomplete:
397+// case openai.AssistantStreamEventThreadMessageIncomplete:
373−// case AssistantStreamEventErrorEvent:
398+// case openai.AssistantStreamEventErrorEvent:
374// default:
399// default:
375// fmt.Errorf("no variant present")
400// fmt.Errorf("no variant present")
376// }
401// }
377−func (u AssistantStreamEventUnion) AsAny() any {
402+func (u AssistantStreamEventUnion) AsAny() anyAssistantStreamEvent {
378 switch u.Event {
403 switch u.Event {
379 case "thread.created":
404 case "thread.created":
380 return u.AsThreadCreated()
405 return u.AsThreadCreated()
@@ -632,46 +657,46 @@ type AssistantStreamEventUnionData struct {
632 // This field is from variant [shared.ErrorObject].
657 // This field is from variant [shared.ErrorObject].
633 Param string `json:"param"`
658 Param string `json:"param"`
634 JSON struct {
659 JSON struct {
635− ID resp.Field
660+ ID respjson.Field
636− CreatedAt resp.Field
661+ CreatedAt respjson.Field
637− Metadata resp.Field
662+ Metadata respjson.Field
638− Object resp.Field
663+ Object respjson.Field
639− ToolResources resp.Field
664+ ToolResources respjson.Field
640− AssistantID resp.Field
665+ AssistantID respjson.Field
641− CancelledAt resp.Field
666+ CancelledAt respjson.Field
642− CompletedAt resp.Field
667+ CompletedAt respjson.Field
643− ExpiresAt resp.Field
668+ ExpiresAt respjson.Field
644− FailedAt resp.Field
669+ FailedAt respjson.Field
645− IncompleteDetails resp.Field
670+ IncompleteDetails respjson.Field
646− Instructions resp.Field
671+ Instructions respjson.Field
647− LastError resp.Field
672+ LastError respjson.Field
648− MaxCompletionTokens resp.Field
673+ MaxCompletionTokens respjson.Field
649− MaxPromptTokens resp.Field
674+ MaxPromptTokens respjson.Field
650− Model resp.Field
675+ Model respjson.Field
651− ParallelToolCalls resp.Field
676+ ParallelToolCalls respjson.Field
652− RequiredAction resp.Field
677+ RequiredAction respjson.Field
653− ResponseFormat resp.Field
678+ ResponseFormat respjson.Field
654− StartedAt resp.Field
679+ StartedAt respjson.Field
655− Status resp.Field
680+ Status respjson.Field
656− ThreadID resp.Field
681+ ThreadID respjson.Field
657− ToolChoice resp.Field
682+ ToolChoice respjson.Field
658− Tools resp.Field
683+ Tools respjson.Field
659− TruncationStrategy resp.Field
684+ TruncationStrategy respjson.Field
660− Usage resp.Field
685+ Usage respjson.Field
661− Temperature resp.Field
686+ Temperature respjson.Field
662− TopP resp.Field
687+ TopP respjson.Field
663− ExpiredAt resp.Field
688+ ExpiredAt respjson.Field
664− RunID resp.Field
689+ RunID respjson.Field
665− StepDetails resp.Field
690+ StepDetails respjson.Field
666− Type resp.Field
691+ Type respjson.Field
667− Delta resp.Field
692+ Delta respjson.Field
668− Attachments resp.Field
693+ Attachments respjson.Field
669− Content resp.Field
694+ Content respjson.Field
670− IncompleteAt resp.Field
695+ IncompleteAt respjson.Field
671− Role resp.Field
696+ Role respjson.Field
672− Code resp.Field
697+ Code respjson.Field
673− Message resp.Field
698+ Message respjson.Field
674− Param resp.Field
699+ Param respjson.Field
675 raw string
700 raw string
676 } `json:"-"`
701 } `json:"-"`
677}
702}
@@ -689,7 +714,7 @@ func (r *AssistantStreamEventUnionData) UnmarshalJSON(data []byte) error {
689type AssistantStreamEventUnionDataIncompleteDetails struct {
714type AssistantStreamEventUnionDataIncompleteDetails struct {
690 Reason string `json:"reason"`
715 Reason string `json:"reason"`
691 JSON struct {
716 JSON struct {
692− Reason resp.Field
717+ Reason respjson.Field
693 raw string
718 raw string
694 } `json:"-"`
719 } `json:"-"`
695}
720}
@@ -708,8 +733,8 @@ type AssistantStreamEventUnionDataLastError struct {
708 Code string `json:"code"`
733 Code string `json:"code"`
709 Message string `json:"message"`
734 Message string `json:"message"`
710 JSON struct {
735 JSON struct {
711− Code resp.Field
736+ Code respjson.Field
712− Message resp.Field
737+ Message respjson.Field
713 raw string
738 raw string
714 } `json:"-"`
739 } `json:"-"`
715}
740}
@@ -729,9 +754,9 @@ type AssistantStreamEventUnionDataUsage struct {
729 PromptTokens int64 `json:"prompt_tokens"`
754 PromptTokens int64 `json:"prompt_tokens"`
730 TotalTokens int64 `json:"total_tokens"`
755 TotalTokens int64 `json:"total_tokens"`
731 JSON struct {
756 JSON struct {
732− CompletionTokens resp.Field
757+ CompletionTokens respjson.Field
733− PromptTokens resp.Field
758+ PromptTokens respjson.Field
734− TotalTokens resp.Field
759+ TotalTokens respjson.Field
735 raw string
760 raw string
736 } `json:"-"`
761 } `json:"-"`
737}
762}
@@ -754,9 +779,9 @@ type AssistantStreamEventUnionDataDelta struct {
754 // This field is from variant [MessageDelta].
779 // This field is from variant [MessageDelta].
755 Role MessageDeltaRole `json:"role"`
780 Role MessageDeltaRole `json:"role"`
756 JSON struct {
781 JSON struct {
757− StepDetails resp.Field
782+ StepDetails respjson.Field
758− Content resp.Field
783+ Content respjson.Field
759− Role resp.Field
784+ Role respjson.Field
760 raw string
785 raw string
761 } `json:"-"`
786 } `json:"-"`
762}
787}
@@ -775,13 +800,12 @@ type AssistantStreamEventThreadCreated struct {
775 Event constant.ThreadCreated `json:"event,required"`
800 Event constant.ThreadCreated `json:"event,required"`
776 // Whether to enable input audio transcription.
801 // Whether to enable input audio transcription.
777 Enabled bool `json:"enabled"`
802 Enabled bool `json:"enabled"`
778− // Metadata for the response, check the presence of optional fields with the
803+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
779− // [resp.Field.IsPresent] method.
780 JSON struct {
804 JSON struct {
781− Data resp.Field
805+ Data respjson.Field
782− Event resp.Field
806+ Event respjson.Field
783− Enabled resp.Field
807+ Enabled respjson.Field
784− ExtraFields map[string]resp.Field
808+ ExtraFields map[string]respjson.Field
785 raw string
809 raw string
786 } `json:"-"`
810 } `json:"-"`
787}
811}
@@ -799,12 +823,11 @@ type AssistantStreamEventThreadRunCreated struct {
799 // [thread](https://platform.openai.com/docs/api-reference/threads).
823 // [thread](https://platform.openai.com/docs/api-reference/threads).
800 Data Run `json:"data,required"`
824 Data Run `json:"data,required"`
801 Event constant.ThreadRunCreated `json:"event,required"`
825 Event constant.ThreadRunCreated `json:"event,required"`
802− // Metadata for the response, check the presence of optional fields with the
826+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
803− // [resp.Field.IsPresent] method.
804 JSON struct {
827 JSON struct {
805− Data resp.Field
828+ Data respjson.Field
806− Event resp.Field
829+ Event respjson.Field
807− ExtraFields map[string]resp.Field
830+ ExtraFields map[string]respjson.Field
808 raw string
831 raw string
809 } `json:"-"`
832 } `json:"-"`
810}
833}
@@ -822,12 +845,11 @@ type AssistantStreamEventThreadRunQueued struct {
822 // [thread](https://platform.openai.com/docs/api-reference/threads).
845 // [thread](https://platform.openai.com/docs/api-reference/threads).
823 Data Run `json:"data,required"`
846 Data Run `json:"data,required"`
824 Event constant.ThreadRunQueued `json:"event,required"`
847 Event constant.ThreadRunQueued `json:"event,required"`
825− // Metadata for the response, check the presence of optional fields with the
848+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
826− // [resp.Field.IsPresent] method.
827 JSON struct {
849 JSON struct {
828− Data resp.Field
850+ Data respjson.Field
829− Event resp.Field
851+ Event respjson.Field
830− ExtraFields map[string]resp.Field
852+ ExtraFields map[string]respjson.Field
831 raw string
853 raw string
832 } `json:"-"`
854 } `json:"-"`
833}
855}
@@ -845,12 +867,11 @@ type AssistantStreamEventThreadRunInProgress struct {
845 // [thread](https://platform.openai.com/docs/api-reference/threads).
867 // [thread](https://platform.openai.com/docs/api-reference/threads).
846 Data Run `json:"data,required"`
868 Data Run `json:"data,required"`
847 Event constant.ThreadRunInProgress `json:"event,required"`
869 Event constant.ThreadRunInProgress `json:"event,required"`
848− // Metadata for the response, check the presence of optional fields with the
870+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
849− // [resp.Field.IsPresent] method.
850 JSON struct {
871 JSON struct {
851− Data resp.Field
872+ Data respjson.Field
852− Event resp.Field
873+ Event respjson.Field
853− ExtraFields map[string]resp.Field
874+ ExtraFields map[string]respjson.Field
854 raw string
875 raw string
855 } `json:"-"`
876 } `json:"-"`
856}
877}
@@ -868,12 +889,11 @@ type AssistantStreamEventThreadRunRequiresAction struct {
868 // [thread](https://platform.openai.com/docs/api-reference/threads).
889 // [thread](https://platform.openai.com/docs/api-reference/threads).
869 Data Run `json:"data,required"`
890 Data Run `json:"data,required"`
870 Event constant.ThreadRunRequiresAction `json:"event,required"`
891 Event constant.ThreadRunRequiresAction `json:"event,required"`
871− // Metadata for the response, check the presence of optional fields with the
892+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
872− // [resp.Field.IsPresent] method.
873 JSON struct {
893 JSON struct {
874− Data resp.Field
894+ Data respjson.Field
875− Event resp.Field
895+ Event respjson.Field
876− ExtraFields map[string]resp.Field
896+ ExtraFields map[string]respjson.Field
877 raw string
897 raw string
878 } `json:"-"`
898 } `json:"-"`
879}
899}
@@ -891,12 +911,11 @@ type AssistantStreamEventThreadRunCompleted struct {
891 // [thread](https://platform.openai.com/docs/api-reference/threads).
911 // [thread](https://platform.openai.com/docs/api-reference/threads).
892 Data Run `json:"data,required"`
912 Data Run `json:"data,required"`
893 Event constant.ThreadRunCompleted `json:"event,required"`
913 Event constant.ThreadRunCompleted `json:"event,required"`
894− // Metadata for the response, check the presence of optional fields with the
914+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
895− // [resp.Field.IsPresent] method.
896 JSON struct {
915 JSON struct {
897− Data resp.Field
916+ Data respjson.Field
898− Event resp.Field
917+ Event respjson.Field
899− ExtraFields map[string]resp.Field
918+ ExtraFields map[string]respjson.Field
900 raw string
919 raw string
901 } `json:"-"`
920 } `json:"-"`
902}
921}
@@ -914,12 +933,11 @@ type AssistantStreamEventThreadRunIncomplete struct {
914 // [thread](https://platform.openai.com/docs/api-reference/threads).
933 // [thread](https://platform.openai.com/docs/api-reference/threads).
915 Data Run `json:"data,required"`
934 Data Run `json:"data,required"`
916 Event constant.ThreadRunIncomplete `json:"event,required"`
935 Event constant.ThreadRunIncomplete `json:"event,required"`
917− // Metadata for the response, check the presence of optional fields with the
936+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
918− // [resp.Field.IsPresent] method.
919 JSON struct {
937 JSON struct {
920− Data resp.Field
938+ Data respjson.Field
921− Event resp.Field
939+ Event respjson.Field
922− ExtraFields map[string]resp.Field
940+ ExtraFields map[string]respjson.Field
923 raw string
941 raw string
924 } `json:"-"`
942 } `json:"-"`
925}
943}
@@ -937,12 +955,11 @@ type AssistantStreamEventThreadRunFailed struct {
937 // [thread](https://platform.openai.com/docs/api-reference/threads).
955 // [thread](https://platform.openai.com/docs/api-reference/threads).
938 Data Run `json:"data,required"`
956 Data Run `json:"data,required"`
939 Event constant.ThreadRunFailed `json:"event,required"`
957 Event constant.ThreadRunFailed `json:"event,required"`
940− // Metadata for the response, check the presence of optional fields with the
958+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
941− // [resp.Field.IsPresent] method.
942 JSON struct {
959 JSON struct {
943− Data resp.Field
960+ Data respjson.Field
944− Event resp.Field
961+ Event respjson.Field
945− ExtraFields map[string]resp.Field
962+ ExtraFields map[string]respjson.Field
946 raw string
963 raw string
947 } `json:"-"`
964 } `json:"-"`
948}
965}
@@ -960,12 +977,11 @@ type AssistantStreamEventThreadRunCancelling struct {
960 // [thread](https://platform.openai.com/docs/api-reference/threads).
977 // [thread](https://platform.openai.com/docs/api-reference/threads).
961 Data Run `json:"data,required"`
978 Data Run `json:"data,required"`
962 Event constant.ThreadRunCancelling `json:"event,required"`
979 Event constant.ThreadRunCancelling `json:"event,required"`
963− // Metadata for the response, check the presence of optional fields with the
980+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
964− // [resp.Field.IsPresent] method.
965 JSON struct {
981 JSON struct {
966− Data resp.Field
982+ Data respjson.Field
967− Event resp.Field
983+ Event respjson.Field
968− ExtraFields map[string]resp.Field
984+ ExtraFields map[string]respjson.Field
969 raw string
985 raw string
970 } `json:"-"`
986 } `json:"-"`
971}
987}
@@ -983,12 +999,11 @@ type AssistantStreamEventThreadRunCancelled struct {
983 // [thread](https://platform.openai.com/docs/api-reference/threads).
999 // [thread](https://platform.openai.com/docs/api-reference/threads).
984 Data Run `json:"data,required"`
1000 Data Run `json:"data,required"`
985 Event constant.ThreadRunCancelled `json:"event,required"`
1001 Event constant.ThreadRunCancelled `json:"event,required"`
986− // Metadata for the response, check the presence of optional fields with the
1002+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
987− // [resp.Field.IsPresent] method.
988 JSON struct {
1003 JSON struct {
989− Data resp.Field
1004+ Data respjson.Field
990− Event resp.Field
1005+ Event respjson.Field
991− ExtraFields map[string]resp.Field
1006+ ExtraFields map[string]respjson.Field
992 raw string
1007 raw string
993 } `json:"-"`
1008 } `json:"-"`
994}
1009}
@@ -1006,12 +1021,11 @@ type AssistantStreamEventThreadRunExpired struct {
1006 // [thread](https://platform.openai.com/docs/api-reference/threads).
1021 // [thread](https://platform.openai.com/docs/api-reference/threads).
1007 Data Run `json:"data,required"`
1022 Data Run `json:"data,required"`
1008 Event constant.ThreadRunExpired `json:"event,required"`
1023 Event constant.ThreadRunExpired `json:"event,required"`
1009− // Metadata for the response, check the presence of optional fields with the
1024+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1010− // [resp.Field.IsPresent] method.
1011 JSON struct {
1025 JSON struct {
1012− Data resp.Field
1026+ Data respjson.Field
1013− Event resp.Field
1027+ Event respjson.Field
1014− ExtraFields map[string]resp.Field
1028+ ExtraFields map[string]respjson.Field
1015 raw string
1029 raw string
1016 } `json:"-"`
1030 } `json:"-"`
1017}
1031}
@@ -1029,12 +1043,11 @@ type AssistantStreamEventThreadRunStepCreated struct {
1029 // Represents a step in execution of a run.
1043 // Represents a step in execution of a run.
1030 Data RunStep `json:"data,required"`
1044 Data RunStep `json:"data,required"`
1031 Event constant.ThreadRunStepCreated `json:"event,required"`
1045 Event constant.ThreadRunStepCreated `json:"event,required"`
1032− // Metadata for the response, check the presence of optional fields with the
1046+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1033− // [resp.Field.IsPresent] method.
1034 JSON struct {
1047 JSON struct {
1035− Data resp.Field
1048+ Data respjson.Field
1036− Event resp.Field
1049+ Event respjson.Field
1037− ExtraFields map[string]resp.Field
1050+ ExtraFields map[string]respjson.Field
1038 raw string
1051 raw string
1039 } `json:"-"`
1052 } `json:"-"`
1040}
1053}
@@ -1052,12 +1065,11 @@ type AssistantStreamEventThreadRunStepInProgress struct {
1052 // Represents a step in execution of a run.
1065 // Represents a step in execution of a run.
1053 Data RunStep `json:"data,required"`
1066 Data RunStep `json:"data,required"`
1054 Event constant.ThreadRunStepInProgress `json:"event,required"`
1067 Event constant.ThreadRunStepInProgress `json:"event,required"`
1055− // Metadata for the response, check the presence of optional fields with the
1068+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1056− // [resp.Field.IsPresent] method.
1057 JSON struct {
1069 JSON struct {
1058− Data resp.Field
1070+ Data respjson.Field
1059− Event resp.Field
1071+ Event respjson.Field
1060− ExtraFields map[string]resp.Field
1072+ ExtraFields map[string]respjson.Field
1061 raw string
1073 raw string
1062 } `json:"-"`
1074 } `json:"-"`
1063}
1075}
@@ -1076,12 +1088,11 @@ type AssistantStreamEventThreadRunStepDelta struct {
1076 // streaming.
1088 // streaming.
1077 Data RunStepDeltaEvent `json:"data,required"`
1089 Data RunStepDeltaEvent `json:"data,required"`
1078 Event constant.ThreadRunStepDelta `json:"event,required"`
1090 Event constant.ThreadRunStepDelta `json:"event,required"`
1079− // Metadata for the response, check the presence of optional fields with the
1091+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1080− // [resp.Field.IsPresent] method.
1081 JSON struct {
1092 JSON struct {
1082− Data resp.Field
1093+ Data respjson.Field
1083− Event resp.Field
1094+ Event respjson.Field
1084− ExtraFields map[string]resp.Field
1095+ ExtraFields map[string]respjson.Field
1085 raw string
1096 raw string
1086 } `json:"-"`
1097 } `json:"-"`
1087}
1098}
@@ -1099,12 +1110,11 @@ type AssistantStreamEventThreadRunStepCompleted struct {
1099 // Represents a step in execution of a run.
1110 // Represents a step in execution of a run.
1100 Data RunStep `json:"data,required"`
1111 Data RunStep `json:"data,required"`
1101 Event constant.ThreadRunStepCompleted `json:"event,required"`
1112 Event constant.ThreadRunStepCompleted `json:"event,required"`
1102− // Metadata for the response, check the presence of optional fields with the
1113+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1103− // [resp.Field.IsPresent] method.
1104 JSON struct {
1114 JSON struct {
1105− Data resp.Field
1115+ Data respjson.Field
1106− Event resp.Field
1116+ Event respjson.Field
1107− ExtraFields map[string]resp.Field
1117+ ExtraFields map[string]respjson.Field
1108 raw string
1118 raw string
1109 } `json:"-"`
1119 } `json:"-"`
1110}
1120}
@@ -1122,12 +1132,11 @@ type AssistantStreamEventThreadRunStepFailed struct {
1122 // Represents a step in execution of a run.
1132 // Represents a step in execution of a run.
1123 Data RunStep `json:"data,required"`
1133 Data RunStep `json:"data,required"`
1124 Event constant.ThreadRunStepFailed `json:"event,required"`
1134 Event constant.ThreadRunStepFailed `json:"event,required"`
1125− // Metadata for the response, check the presence of optional fields with the
1135+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1126− // [resp.Field.IsPresent] method.
1127 JSON struct {
1136 JSON struct {
1128− Data resp.Field
1137+ Data respjson.Field
1129− Event resp.Field
1138+ Event respjson.Field
1130− ExtraFields map[string]resp.Field
1139+ ExtraFields map[string]respjson.Field
1131 raw string
1140 raw string
1132 } `json:"-"`
1141 } `json:"-"`
1133}
1142}
@@ -1145,12 +1154,11 @@ type AssistantStreamEventThreadRunStepCancelled struct {
1145 // Represents a step in execution of a run.
1154 // Represents a step in execution of a run.
1146 Data RunStep `json:"data,required"`
1155 Data RunStep `json:"data,required"`
1147 Event constant.ThreadRunStepCancelled `json:"event,required"`
1156 Event constant.ThreadRunStepCancelled `json:"event,required"`
1148− // Metadata for the response, check the presence of optional fields with the
1157+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1149− // [resp.Field.IsPresent] method.
1150 JSON struct {
1158 JSON struct {
1151− Data resp.Field
1159+ Data respjson.Field
1152− Event resp.Field
1160+ Event respjson.Field
1153− ExtraFields map[string]resp.Field
1161+ ExtraFields map[string]respjson.Field
1154 raw string
1162 raw string
1155 } `json:"-"`
1163 } `json:"-"`
1156}
1164}
@@ -1168,12 +1176,11 @@ type AssistantStreamEventThreadRunStepExpired struct {
1168 // Represents a step in execution of a run.
1176 // Represents a step in execution of a run.
1169 Data RunStep `json:"data,required"`
1177 Data RunStep `json:"data,required"`
1170 Event constant.ThreadRunStepExpired `json:"event,required"`
1178 Event constant.ThreadRunStepExpired `json:"event,required"`
1171− // Metadata for the response, check the presence of optional fields with the
1179+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1172− // [resp.Field.IsPresent] method.
1173 JSON struct {
1180 JSON struct {
1174− Data resp.Field
1181+ Data respjson.Field
1175− Event resp.Field
1182+ Event respjson.Field
1176− ExtraFields map[string]resp.Field
1183+ ExtraFields map[string]respjson.Field
1177 raw string
1184 raw string
1178 } `json:"-"`
1185 } `json:"-"`
1179}
1186}
@@ -1192,12 +1199,11 @@ type AssistantStreamEventThreadMessageCreated struct {
1192 // [thread](https://platform.openai.com/docs/api-reference/threads).
1199 // [thread](https://platform.openai.com/docs/api-reference/threads).
1193 Data Message `json:"data,required"`
1200 Data Message `json:"data,required"`
1194 Event constant.ThreadMessageCreated `json:"event,required"`
1201 Event constant.ThreadMessageCreated `json:"event,required"`
1195− // Metadata for the response, check the presence of optional fields with the
1202+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1196− // [resp.Field.IsPresent] method.
1197 JSON struct {
1203 JSON struct {
1198− Data resp.Field
1204+ Data respjson.Field
1199− Event resp.Field
1205+ Event respjson.Field
1200− ExtraFields map[string]resp.Field
1206+ ExtraFields map[string]respjson.Field
1201 raw string
1207 raw string
1202 } `json:"-"`
1208 } `json:"-"`
1203}
1209}
@@ -1216,12 +1222,11 @@ type AssistantStreamEventThreadMessageInProgress struct {
1216 // [thread](https://platform.openai.com/docs/api-reference/threads).
1222 // [thread](https://platform.openai.com/docs/api-reference/threads).
1217 Data Message `json:"data,required"`
1223 Data Message `json:"data,required"`
1218 Event constant.ThreadMessageInProgress `json:"event,required"`
1224 Event constant.ThreadMessageInProgress `json:"event,required"`
1219− // Metadata for the response, check the presence of optional fields with the
1225+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1220− // [resp.Field.IsPresent] method.
1221 JSON struct {
1226 JSON struct {
1222− Data resp.Field
1227+ Data respjson.Field
1223− Event resp.Field
1228+ Event respjson.Field
1224− ExtraFields map[string]resp.Field
1229+ ExtraFields map[string]respjson.Field
1225 raw string
1230 raw string
1226 } `json:"-"`
1231 } `json:"-"`
1227}
1232}
@@ -1240,12 +1245,11 @@ type AssistantStreamEventThreadMessageDelta struct {
1240 // streaming.
1245 // streaming.
1241 Data MessageDeltaEvent `json:"data,required"`
1246 Data MessageDeltaEvent `json:"data,required"`
1242 Event constant.ThreadMessageDelta `json:"event,required"`
1247 Event constant.ThreadMessageDelta `json:"event,required"`
1243− // Metadata for the response, check the presence of optional fields with the
1248+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1244− // [resp.Field.IsPresent] method.
1245 JSON struct {
1249 JSON struct {
1246− Data resp.Field
1250+ Data respjson.Field
1247− Event resp.Field
1251+ Event respjson.Field
1248− ExtraFields map[string]resp.Field
1252+ ExtraFields map[string]respjson.Field
1249 raw string
1253 raw string
1250 } `json:"-"`
1254 } `json:"-"`
1251}
1255}
@@ -1264,12 +1268,11 @@ type AssistantStreamEventThreadMessageCompleted struct {
1264 // [thread](https://platform.openai.com/docs/api-reference/threads).
1268 // [thread](https://platform.openai.com/docs/api-reference/threads).
1265 Data Message `json:"data,required"`
1269 Data Message `json:"data,required"`
1266 Event constant.ThreadMessageCompleted `json:"event,required"`
1270 Event constant.ThreadMessageCompleted `json:"event,required"`
1267− // Metadata for the response, check the presence of optional fields with the
1271+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1268− // [resp.Field.IsPresent] method.
1269 JSON struct {
1272 JSON struct {
1270− Data resp.Field
1273+ Data respjson.Field
1271− Event resp.Field
1274+ Event respjson.Field
1272− ExtraFields map[string]resp.Field
1275+ ExtraFields map[string]respjson.Field
1273 raw string
1276 raw string
1274 } `json:"-"`
1277 } `json:"-"`
1275}
1278}
@@ -1288,12 +1291,11 @@ type AssistantStreamEventThreadMessageIncomplete struct {
1288 // [thread](https://platform.openai.com/docs/api-reference/threads).
1291 // [thread](https://platform.openai.com/docs/api-reference/threads).
1289 Data Message `json:"data,required"`
1292 Data Message `json:"data,required"`
1290 Event constant.ThreadMessageIncomplete `json:"event,required"`
1293 Event constant.ThreadMessageIncomplete `json:"event,required"`
1291− // Metadata for the response, check the presence of optional fields with the
1294+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1292− // [resp.Field.IsPresent] method.
1293 JSON struct {
1295 JSON struct {
1294− Data resp.Field
1296+ Data respjson.Field
1295− Event resp.Field
1297+ Event respjson.Field
1296− ExtraFields map[string]resp.Field
1298+ ExtraFields map[string]respjson.Field
1297 raw string
1299 raw string
1298 } `json:"-"`
1300 } `json:"-"`
1299}
1301}
@@ -1310,12 +1312,11 @@ func (r *AssistantStreamEventThreadMessageIncomplete) UnmarshalJSON(data []byte)
1310type AssistantStreamEventErrorEvent struct {
1312type AssistantStreamEventErrorEvent struct {
1311 Data shared.ErrorObject `json:"data,required"`
1313 Data shared.ErrorObject `json:"data,required"`
1312 Event constant.Error `json:"event,required"`
1314 Event constant.Error `json:"event,required"`
1313− // Metadata for the response, check the presence of optional fields with the
1315+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1314− // [resp.Field.IsPresent] method.
1315 JSON struct {
1316 JSON struct {
1316− Data resp.Field
1317+ Data respjson.Field
1317− Event resp.Field
1318+ Event respjson.Field
1318− ExtraFields map[string]resp.Field
1319+ ExtraFields map[string]respjson.Field
1319 raw string
1320 raw string
1320 } `json:"-"`
1321 } `json:"-"`
1321}
1322}
@@ -1340,23 +1341,33 @@ type AssistantToolUnion struct {
1340 // This field is from variant [FunctionTool].
1341 // This field is from variant [FunctionTool].
1341 Function shared.FunctionDefinition `json:"function"`
1342 Function shared.FunctionDefinition `json:"function"`
1342 JSON struct {
1343 JSON struct {
1343− Type resp.Field
1344+ Type respjson.Field
1344− FileSearch resp.Field
1345+ FileSearch respjson.Field
1345− Function resp.Field
1346+ Function respjson.Field
1346 raw string
1347 raw string
1347 } `json:"-"`
1348 } `json:"-"`
1348}
1349}
1349
1350
1351+// anyAssistantTool is implemented by each variant of [AssistantToolUnion] to add
1352+// type safety for the return type of [AssistantToolUnion.AsAny]
1353+type anyAssistantTool interface {
1354+ implAssistantToolUnion()
1355+}
1356+
1357+func (CodeInterpreterTool) implAssistantToolUnion() {}
1358+func (FileSearchTool) implAssistantToolUnion() {}
1359+func (FunctionTool) implAssistantToolUnion() {}
1360+
1350// Use the following switch statement to find the correct variant
1361// Use the following switch statement to find the correct variant
1351//
1362//
1352// switch variant := AssistantToolUnion.AsAny().(type) {
1363// switch variant := AssistantToolUnion.AsAny().(type) {
1353−// case CodeInterpreterTool:
1364+// case openai.CodeInterpreterTool:
1354−// case FileSearchTool:
1365+// case openai.FileSearchTool:
1355−// case FunctionTool:
1366+// case openai.FunctionTool:
1356// default:
1367// default:
1357// fmt.Errorf("no variant present")
1368// fmt.Errorf("no variant present")
1358// }
1369// }
1359−func (u AssistantToolUnion) AsAny() any {
1370+func (u AssistantToolUnion) AsAny() anyAssistantTool {
1360 switch u.Type {
1371 switch u.Type {
1361 case "code_interpreter":
1372 case "code_interpreter":
1362 return u.AsCodeInterpreter()
1373 return u.AsCodeInterpreter()
@@ -1394,9 +1405,9 @@ func (r *AssistantToolUnion) UnmarshalJSON(data []byte) error {
1394//
1405//
1395// Warning: the fields of the param type will not be present. ToParam should only
1406// Warning: the fields of the param type will not be present. ToParam should only
1396// be used at the last possible moment before sending a request. Test for this with
1407// be used at the last possible moment before sending a request. Test for this with
1397−// AssistantToolUnionParam.IsOverridden()
1408+// AssistantToolUnionParam.Overrides()
1398func (r AssistantToolUnion) ToParam() AssistantToolUnionParam {
1409func (r AssistantToolUnion) ToParam() AssistantToolUnionParam {
1399− return param.OverrideObj[AssistantToolUnionParam](r.RawJSON())
1410+ return param.Override[AssistantToolUnionParam](json.RawMessage(r.RawJSON()))
1400}
1411}
1401
1412
1402func AssistantToolParamOfFunction(function shared.FunctionDefinitionParam) AssistantToolUnionParam {
1413func AssistantToolParamOfFunction(function shared.FunctionDefinitionParam) AssistantToolUnionParam {
@@ -1415,11 +1426,11 @@ type AssistantToolUnionParam struct {
1415 paramUnion
1426 paramUnion
1416}
1427}
1417
1428
1418−// IsPresent returns true if the field's value is not omitted and not the JSON
1419−// "null". To check if this field is omitted, use [param.IsOmitted].
1420−func (u AssistantToolUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
1421func (u AssistantToolUnionParam) MarshalJSON() ([]byte, error) {
1429func (u AssistantToolUnionParam) MarshalJSON() ([]byte, error) {
1422− return param.MarshalUnion[AssistantToolUnionParam](u.OfCodeInterpreter, u.OfFileSearch, u.OfFunction)
1430+ return param.MarshalUnion(u, u.OfCodeInterpreter, u.OfFileSearch, u.OfFunction)
1431+}
1432+func (u *AssistantToolUnionParam) UnmarshalJSON(data []byte) error {
1433+ return apijson.UnmarshalRoot(data, u)
1423}
1434}
1424
1435
1425func (u *AssistantToolUnionParam) asAny() any {
1436func (u *AssistantToolUnionParam) asAny() any {
@@ -1464,32 +1475,19 @@ func (u AssistantToolUnionParam) GetType() *string {
1464func init() {
1475func init() {
1465 apijson.RegisterUnion[AssistantToolUnionParam](
1476 apijson.RegisterUnion[AssistantToolUnionParam](
1466 "type",
1477 "type",
1467− apijson.UnionVariant{
1468− TypeFilter: gjson.JSON,
1469− Type: reflect.TypeOf(CodeInterpreterToolParam{}),
1478+ apijson.Discriminator[CodeInterpreterToolParam]("code_interpreter"),
1470− DiscriminatorValue: "code_interpreter",
1471− },
1472− apijson.UnionVariant{
1473− TypeFilter: gjson.JSON,
1474− Type: reflect.TypeOf(FileSearchToolParam{}),
1479+ apijson.Discriminator[FileSearchToolParam]("file_search"),
1475− DiscriminatorValue: "file_search",
1476− },
1477− apijson.UnionVariant{
1478− TypeFilter: gjson.JSON,
1479− Type: reflect.TypeOf(FunctionToolParam{}),
1480+ apijson.Discriminator[FunctionToolParam]("function"),
1480− DiscriminatorValue: "function",
1481− },
1482 )
1481 )
1483}
1482}
1484
1483
1485type CodeInterpreterTool struct {
1484type CodeInterpreterTool struct {
1486 // The type of tool being defined: `code_interpreter`
1485 // The type of tool being defined: `code_interpreter`
1487 Type constant.CodeInterpreter `json:"type,required"`
1486 Type constant.CodeInterpreter `json:"type,required"`
1488− // Metadata for the response, check the presence of optional fields with the
1487+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1489− // [resp.Field.IsPresent] method.
1490 JSON struct {
1488 JSON struct {
1491− Type resp.Field
1489+ Type respjson.Field
1492− ExtraFields map[string]resp.Field
1490+ ExtraFields map[string]respjson.Field
1493 raw string
1491 raw string
1494 } `json:"-"`
1492 } `json:"-"`
1495}
1493}
@@ -1504,39 +1502,43 @@ func (r *CodeInterpreterTool) UnmarshalJSON(data []byte) error {
1504//
1502//
1505// Warning: the fields of the param type will not be present. ToParam should only
1503// Warning: the fields of the param type will not be present. ToParam should only
1506// be used at the last possible moment before sending a request. Test for this with
1504// be used at the last possible moment before sending a request. Test for this with
1507−// CodeInterpreterToolParam.IsOverridden()
1505+// CodeInterpreterToolParam.Overrides()
1508func (r CodeInterpreterTool) ToParam() CodeInterpreterToolParam {
1506func (r CodeInterpreterTool) ToParam() CodeInterpreterToolParam {
1509− return param.OverrideObj[CodeInterpreterToolParam](r.RawJSON())
1507+ return param.Override[CodeInterpreterToolParam](json.RawMessage(r.RawJSON()))
1510}
1508}
1511
1509
1512−// The property Type is required.
1510+func NewCodeInterpreterToolParam() CodeInterpreterToolParam {
1511+ return CodeInterpreterToolParam{
1512+ Type: "code_interpreter",
1513+ }
1514+}
1515+
1516+// This struct has a constant value, construct it with
1517+// [NewCodeInterpreterToolParam].
1513type CodeInterpreterToolParam struct {
1518type CodeInterpreterToolParam struct {
1514 // The type of tool being defined: `code_interpreter`
1519 // The type of tool being defined: `code_interpreter`
1515− //
1516− // This field can be elided, and will marshal its zero value as "code_interpreter".
1517 Type constant.CodeInterpreter `json:"type,required"`
1520 Type constant.CodeInterpreter `json:"type,required"`
1518 paramObj
1521 paramObj
1519}
1522}
1520
1523
1521−// IsPresent returns true if the field's value is not omitted and not the JSON
1522−// "null". To check if this field is omitted, use [param.IsOmitted].
1523−func (f CodeInterpreterToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1524func (r CodeInterpreterToolParam) MarshalJSON() (data []byte, err error) {
1524func (r CodeInterpreterToolParam) MarshalJSON() (data []byte, err error) {
1525 type shadow CodeInterpreterToolParam
1525 type shadow CodeInterpreterToolParam
1526 return param.MarshalObject(r, (*shadow)(&r))
1526 return param.MarshalObject(r, (*shadow)(&r))
1527}
1527}
1528+func (r *CodeInterpreterToolParam) UnmarshalJSON(data []byte) error {
1529+ return apijson.UnmarshalRoot(data, r)
1530+}
1528
1531
1529type FileSearchTool struct {
1532type FileSearchTool struct {
1530 // The type of tool being defined: `file_search`
1533 // The type of tool being defined: `file_search`
1531 Type constant.FileSearch `json:"type,required"`
1534 Type constant.FileSearch `json:"type,required"`
1532 // Overrides for the file search tool.
1535 // Overrides for the file search tool.
1533 FileSearch FileSearchToolFileSearch `json:"file_search"`
1536 FileSearch FileSearchToolFileSearch `json:"file_search"`
1534− // Metadata for the response, check the presence of optional fields with the
1537+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1535− // [resp.Field.IsPresent] method.
1536 JSON struct {
1538 JSON struct {
1537− Type resp.Field
1539+ Type respjson.Field
1538− FileSearch resp.Field
1540+ FileSearch respjson.Field
1539− ExtraFields map[string]resp.Field
1541+ ExtraFields map[string]respjson.Field
1540 raw string
1542 raw string
1541 } `json:"-"`
1543 } `json:"-"`
1542}
1544}
@@ -1551,9 +1553,9 @@ func (r *FileSearchTool) UnmarshalJSON(data []byte) error {
1551//
1553//
1552// Warning: the fields of the param type will not be present. ToParam should only
1554// Warning: the fields of the param type will not be present. ToParam should only
1553// be used at the last possible moment before sending a request. Test for this with
1555// be used at the last possible moment before sending a request. Test for this with
1554−// FileSearchToolParam.IsOverridden()
1556+// FileSearchToolParam.Overrides()
1555func (r FileSearchTool) ToParam() FileSearchToolParam {
1557func (r FileSearchTool) ToParam() FileSearchToolParam {
1556− return param.OverrideObj[FileSearchToolParam](r.RawJSON())
1558+ return param.Override[FileSearchToolParam](json.RawMessage(r.RawJSON()))
1557}
1559}
1558
1560
1559// Overrides for the file search tool.
1561// Overrides for the file search tool.
@@ -1574,12 +1576,11 @@ type FileSearchToolFileSearch struct {
1574 // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings)
1576 // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings)
1575 // for more information.
1577 // for more information.
1576 RankingOptions FileSearchToolFileSearchRankingOptions `json:"ranking_options"`
1578 RankingOptions FileSearchToolFileSearchRankingOptions `json:"ranking_options"`
1577− // Metadata for the response, check the presence of optional fields with the
1579+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1578− // [resp.Field.IsPresent] method.
1579 JSON struct {
1580 JSON struct {
1580− MaxNumResults resp.Field
1581+ MaxNumResults respjson.Field
1581− RankingOptions resp.Field
1582+ RankingOptions respjson.Field
1582− ExtraFields map[string]resp.Field
1583+ ExtraFields map[string]respjson.Field
1583 raw string
1584 raw string
1584 } `json:"-"`
1585 } `json:"-"`
1585}
1586}
@@ -1605,12 +1606,11 @@ type FileSearchToolFileSearchRankingOptions struct {
1605 //
1606 //
1606 // Any of "auto", "default_2024_08_21".
1607 // Any of "auto", "default_2024_08_21".
1607 Ranker string `json:"ranker"`
1608 Ranker string `json:"ranker"`
1608− // Metadata for the response, check the presence of optional fields with the
1609+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1609− // [resp.Field.IsPresent] method.
1610 JSON struct {
1610 JSON struct {
1611− ScoreThreshold resp.Field
1611+ ScoreThreshold respjson.Field
1612− Ranker resp.Field
1612+ Ranker respjson.Field
1613− ExtraFields map[string]resp.Field
1613+ ExtraFields map[string]respjson.Field
1614 raw string
1614 raw string
1615 } `json:"-"`
1615 } `json:"-"`
1616}
1616}
@@ -1632,13 +1632,13 @@ type FileSearchToolParam struct {
1632 paramObj
1632 paramObj
1633}
1633}
1634
1634
1635−// IsPresent returns true if the field's value is not omitted and not the JSON
1636−// "null". To check if this field is omitted, use [param.IsOmitted].
1637−func (f FileSearchToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1638func (r FileSearchToolParam) MarshalJSON() (data []byte, err error) {
1635func (r FileSearchToolParam) MarshalJSON() (data []byte, err error) {
1639 type shadow FileSearchToolParam
1636 type shadow FileSearchToolParam
1640 return param.MarshalObject(r, (*shadow)(&r))
1637 return param.MarshalObject(r, (*shadow)(&r))
1641}
1638}
1639+func (r *FileSearchToolParam) UnmarshalJSON(data []byte) error {
1640+ return apijson.UnmarshalRoot(data, r)
1641+}
1642
1642
1643// Overrides for the file search tool.
1643// Overrides for the file search tool.
1644type FileSearchToolFileSearchParam struct {
1644type FileSearchToolFileSearchParam struct {
@@ -1661,13 +1661,13 @@ type FileSearchToolFileSearchParam struct {
1661 paramObj
1661 paramObj
1662}
1662}
1663
1663
1664−// IsPresent returns true if the field's value is not omitted and not the JSON
1665−// "null". To check if this field is omitted, use [param.IsOmitted].
1666−func (f FileSearchToolFileSearchParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1667func (r FileSearchToolFileSearchParam) MarshalJSON() (data []byte, err error) {
1664func (r FileSearchToolFileSearchParam) MarshalJSON() (data []byte, err error) {
1668 type shadow FileSearchToolFileSearchParam
1665 type shadow FileSearchToolFileSearchParam
1669 return param.MarshalObject(r, (*shadow)(&r))
1666 return param.MarshalObject(r, (*shadow)(&r))
1670}
1667}
1668+func (r *FileSearchToolFileSearchParam) UnmarshalJSON(data []byte) error {
1669+ return apijson.UnmarshalRoot(data, r)
1670+}
1671
1671
1672// The ranking options for the file search. If not specified, the file search tool
1672// The ranking options for the file search. If not specified, the file search tool
1673// will use the `auto` ranker and a score_threshold of 0.
1673// will use the `auto` ranker and a score_threshold of 0.
@@ -1689,19 +1689,17 @@ type FileSearchToolFileSearchRankingOptionsParam struct {
1689 paramObj
1689 paramObj
1690}
1690}
1691
1691
1692−// IsPresent returns true if the field's value is not omitted and not the JSON
1693−// "null". To check if this field is omitted, use [param.IsOmitted].
1694−func (f FileSearchToolFileSearchRankingOptionsParam) IsPresent() bool {
1695− return !param.IsOmitted(f) && !f.IsNull()
1696−}
1697func (r FileSearchToolFileSearchRankingOptionsParam) MarshalJSON() (data []byte, err error) {
1692func (r FileSearchToolFileSearchRankingOptionsParam) MarshalJSON() (data []byte, err error) {
1698 type shadow FileSearchToolFileSearchRankingOptionsParam
1693 type shadow FileSearchToolFileSearchRankingOptionsParam
1699 return param.MarshalObject(r, (*shadow)(&r))
1694 return param.MarshalObject(r, (*shadow)(&r))
1700}
1695}
1696+func (r *FileSearchToolFileSearchRankingOptionsParam) UnmarshalJSON(data []byte) error {
1697+ return apijson.UnmarshalRoot(data, r)
1698+}
1701
1699
1702func init() {
1700func init() {
1703 apijson.RegisterFieldValidator[FileSearchToolFileSearchRankingOptionsParam](
1701 apijson.RegisterFieldValidator[FileSearchToolFileSearchRankingOptionsParam](
1704− "Ranker", false, "auto", "default_2024_08_21",
1702+ "ranker", "auto", "default_2024_08_21",
1705 )
1703 )
1706}
1704}
1707
1705
@@ -1709,12 +1707,11 @@ type FunctionTool struct {
1709 Function shared.FunctionDefinition `json:"function,required"`
1707 Function shared.FunctionDefinition `json:"function,required"`
1710 // The type of tool being defined: `function`
1708 // The type of tool being defined: `function`
1711 Type constant.Function `json:"type,required"`
1709 Type constant.Function `json:"type,required"`
1712− // Metadata for the response, check the presence of optional fields with the
1710+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1713− // [resp.Field.IsPresent] method.
1714 JSON struct {
1711 JSON struct {
1715− Function resp.Field
1712+ Function respjson.Field
1716− Type resp.Field
1713+ Type respjson.Field
1717− ExtraFields map[string]resp.Field
1714+ ExtraFields map[string]respjson.Field
1718 raw string
1715 raw string
1719 } `json:"-"`
1716 } `json:"-"`
1720}
1717}
@@ -1729,9 +1726,9 @@ func (r *FunctionTool) UnmarshalJSON(data []byte) error {
1729//
1726//
1730// Warning: the fields of the param type will not be present. ToParam should only
1727// Warning: the fields of the param type will not be present. ToParam should only
1731// be used at the last possible moment before sending a request. Test for this with
1728// be used at the last possible moment before sending a request. Test for this with
1732−// FunctionToolParam.IsOverridden()
1729+// FunctionToolParam.Overrides()
1733func (r FunctionTool) ToParam() FunctionToolParam {
1730func (r FunctionTool) ToParam() FunctionToolParam {
1734− return param.OverrideObj[FunctionToolParam](r.RawJSON())
1731+ return param.Override[FunctionToolParam](json.RawMessage(r.RawJSON()))
1735}
1732}
1736
1733
1737// The properties Function, Type are required.
1734// The properties Function, Type are required.
@@ -1744,13 +1741,13 @@ type FunctionToolParam struct {
1744 paramObj
1741 paramObj
1745}
1742}
1746
1743
1747−// IsPresent returns true if the field's value is not omitted and not the JSON
1748−// "null". To check if this field is omitted, use [param.IsOmitted].
1749−func (f FunctionToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1750func (r FunctionToolParam) MarshalJSON() (data []byte, err error) {
1744func (r FunctionToolParam) MarshalJSON() (data []byte, err error) {
1751 type shadow FunctionToolParam
1745 type shadow FunctionToolParam
1752 return param.MarshalObject(r, (*shadow)(&r))
1746 return param.MarshalObject(r, (*shadow)(&r))
1753}
1747}
1748+func (r *FunctionToolParam) UnmarshalJSON(data []byte) error {
1749+ return apijson.UnmarshalRoot(data, r)
1750+}
1754
1751
1755type BetaAssistantNewParams struct {
1752type BetaAssistantNewParams struct {
1756 // ID of the model to use. You can use the
1753 // ID of the model to use. You can use the
@@ -1782,7 +1779,7 @@ type BetaAssistantNewParams struct {
1782 //
1779 //
1783 // Keys are strings with a maximum length of 64 characters. Values are strings with
1780 // Keys are strings with a maximum length of 64 characters. Values are strings with
1784 // a maximum length of 512 characters.
1781 // a maximum length of 512 characters.
1785− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1782+ Metadata shared.Metadata `json:"metadata,omitzero"`
1786 // **o-series models only**
1783 // **o-series models only**
1787 //
1784 //
1788 // Constrains effort on reasoning for
1785 // Constrains effort on reasoning for
@@ -1825,14 +1822,13 @@ type BetaAssistantNewParams struct {
1825 paramObj
1822 paramObj
1826}
1823}
1827
1824
1828−// IsPresent returns true if the field's value is not omitted and not the JSON
1829−// "null". To check if this field is omitted, use [param.IsOmitted].
1830−func (f BetaAssistantNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1831−
1832func (r BetaAssistantNewParams) MarshalJSON() (data []byte, err error) {
1825func (r BetaAssistantNewParams) MarshalJSON() (data []byte, err error) {
1833 type shadow BetaAssistantNewParams
1826 type shadow BetaAssistantNewParams
1834 return param.MarshalObject(r, (*shadow)(&r))
1827 return param.MarshalObject(r, (*shadow)(&r))
1835}
1828}
1829+func (r *BetaAssistantNewParams) UnmarshalJSON(data []byte) error {
1830+ return apijson.UnmarshalRoot(data, r)
1831+}
1836
1832
1837// A set of resources that are used by the assistant's tools. The resources are
1833// A set of resources that are used by the assistant's tools. The resources are
1838// specific to the type of tool. For example, the `code_interpreter` tool requires
1834// specific to the type of tool. For example, the `code_interpreter` tool requires
@@ -1844,15 +1840,13 @@ type BetaAssistantNewParamsToolResources struct {
1844 paramObj
1840 paramObj
1845}
1841}
1846
1842
1847−// IsPresent returns true if the field's value is not omitted and not the JSON
1848−// "null". To check if this field is omitted, use [param.IsOmitted].
1849−func (f BetaAssistantNewParamsToolResources) IsPresent() bool {
1850− return !param.IsOmitted(f) && !f.IsNull()
1851−}
1852func (r BetaAssistantNewParamsToolResources) MarshalJSON() (data []byte, err error) {
1843func (r BetaAssistantNewParamsToolResources) MarshalJSON() (data []byte, err error) {
1853 type shadow BetaAssistantNewParamsToolResources
1844 type shadow BetaAssistantNewParamsToolResources
1854 return param.MarshalObject(r, (*shadow)(&r))
1845 return param.MarshalObject(r, (*shadow)(&r))
1855}
1846}
1847+func (r *BetaAssistantNewParamsToolResources) UnmarshalJSON(data []byte) error {
1848+ return apijson.UnmarshalRoot(data, r)
1849+}
1856
1850
1857type BetaAssistantNewParamsToolResourcesCodeInterpreter struct {
1851type BetaAssistantNewParamsToolResourcesCodeInterpreter struct {
1858 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
1852 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
@@ -1862,15 +1856,13 @@ type BetaAssistantNewParamsToolResourcesCodeInterpreter struct {
1862 paramObj
1856 paramObj
1863}
1857}
1864
1858
1865−// IsPresent returns true if the field's value is not omitted and not the JSON
1866−// "null". To check if this field is omitted, use [param.IsOmitted].
1867−func (f BetaAssistantNewParamsToolResourcesCodeInterpreter) IsPresent() bool {
1868− return !param.IsOmitted(f) && !f.IsNull()
1869−}
1870func (r BetaAssistantNewParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1859func (r BetaAssistantNewParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1871 type shadow BetaAssistantNewParamsToolResourcesCodeInterpreter
1860 type shadow BetaAssistantNewParamsToolResourcesCodeInterpreter
1872 return param.MarshalObject(r, (*shadow)(&r))
1861 return param.MarshalObject(r, (*shadow)(&r))
1873}
1862}
1863+func (r *BetaAssistantNewParamsToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error {
1864+ return apijson.UnmarshalRoot(data, r)
1865+}
1874
1866
1875type BetaAssistantNewParamsToolResourcesFileSearch struct {
1867type BetaAssistantNewParamsToolResourcesFileSearch struct {
1876 // The
1868 // The
@@ -1886,15 +1878,13 @@ type BetaAssistantNewParamsToolResourcesFileSearch struct {
1886 paramObj
1878 paramObj
1887}
1879}
1888
1880
1889−// IsPresent returns true if the field's value is not omitted and not the JSON
1890−// "null". To check if this field is omitted, use [param.IsOmitted].
1891−func (f BetaAssistantNewParamsToolResourcesFileSearch) IsPresent() bool {
1892− return !param.IsOmitted(f) && !f.IsNull()
1893−}
1894func (r BetaAssistantNewParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1881func (r BetaAssistantNewParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1895 type shadow BetaAssistantNewParamsToolResourcesFileSearch
1882 type shadow BetaAssistantNewParamsToolResourcesFileSearch
1896 return param.MarshalObject(r, (*shadow)(&r))
1883 return param.MarshalObject(r, (*shadow)(&r))
1897}
1884}
1885+func (r *BetaAssistantNewParamsToolResourcesFileSearch) UnmarshalJSON(data []byte) error {
1886+ return apijson.UnmarshalRoot(data, r)
1887+}
1898
1888
1899type BetaAssistantNewParamsToolResourcesFileSearchVectorStore struct {
1889type BetaAssistantNewParamsToolResourcesFileSearchVectorStore struct {
1900 // Set of 16 key-value pairs that can be attached to an object. This can be useful
1890 // Set of 16 key-value pairs that can be attached to an object. This can be useful
@@ -1903,7 +1893,7 @@ type BetaAssistantNewParamsToolResourcesFileSearchVectorStore struct {
1903 //
1893 //
1904 // Keys are strings with a maximum length of 64 characters. Values are strings with
1894 // Keys are strings with a maximum length of 64 characters. Values are strings with
1905 // a maximum length of 512 characters.
1895 // a maximum length of 512 characters.
1906− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1896+ Metadata shared.Metadata `json:"metadata,omitzero"`
1907 // The chunking strategy used to chunk the file(s). If not set, will use the `auto`
1897 // The chunking strategy used to chunk the file(s). If not set, will use the `auto`
1908 // strategy.
1898 // strategy.
1909 ChunkingStrategy BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
1899 ChunkingStrategy BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
@@ -1914,15 +1904,13 @@ type BetaAssistantNewParamsToolResourcesFileSearchVectorStore struct {
1914 paramObj
1904 paramObj
1915}
1905}
1916
1906
1917−// IsPresent returns true if the field's value is not omitted and not the JSON
1918−// "null". To check if this field is omitted, use [param.IsOmitted].
1919−func (f BetaAssistantNewParamsToolResourcesFileSearchVectorStore) IsPresent() bool {
1920− return !param.IsOmitted(f) && !f.IsNull()
1921−}
1922func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) {
1907func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) {
1923 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStore
1908 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStore
1924 return param.MarshalObject(r, (*shadow)(&r))
1909 return param.MarshalObject(r, (*shadow)(&r))
1925}
1910}
1911+func (r *BetaAssistantNewParamsToolResourcesFileSearchVectorStore) UnmarshalJSON(data []byte) error {
1912+ return apijson.UnmarshalRoot(data, r)
1913+}
1926
1914
1927// Only one field can be non-zero.
1915// Only one field can be non-zero.
1928//
1916//
@@ -1933,13 +1921,11 @@ type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUni
1933 paramUnion
1921 paramUnion
1934}
1922}
1935
1923
1936−// IsPresent returns true if the field's value is not omitted and not the JSON
1937−// "null". To check if this field is omitted, use [param.IsOmitted].
1938−func (u BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) IsPresent() bool {
1939− return !param.IsOmitted(u) && !u.IsNull()
1940−}
1941func (u BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
1924func (u BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
1925+ return param.MarshalUnion(u, u.OfAuto, u.OfStatic)
1926+}
1942− return param.MarshalUnion[BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion](u.OfAuto, u.OfStatic)
1927+func (u *BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) UnmarshalJSON(data []byte) error {
1928+ return apijson.UnmarshalRoot(data, u)
1943}
1929}
1944
1930
1945func (u *BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) asAny() any {
1931func (u *BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) asAny() any {
@@ -1972,40 +1958,35 @@ func (u BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategy
1972func init() {
1958func init() {
1973 apijson.RegisterUnion[BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion](
1959 apijson.RegisterUnion[BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion](
1974 "type",
1960 "type",
1975− apijson.UnionVariant{
1976− TypeFilter: gjson.JSON,
1977− Type: reflect.TypeOf(BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto{}),
1961+ apijson.Discriminator[BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto]("auto"),
1978− DiscriminatorValue: "auto",
1979− },
1980− apijson.UnionVariant{
1981− TypeFilter: gjson.JSON,
1982− Type: reflect.TypeOf(BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic{}),
1962+ apijson.Discriminator[BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic]("static"),
1983− DiscriminatorValue: "static",
1984− },
1985 )
1963 )
1986}
1964}
1987
1965
1966+func NewBetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto() BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto {
1967+ return BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto{
1968+ Type: "auto",
1969+ }
1970+}
1971+
1988// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of
1972// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of
1989// `800` and `chunk_overlap_tokens` of `400`.
1973// `800` and `chunk_overlap_tokens` of `400`.
1990//
1974//
1991−// The property Type is required.
1975+// This struct has a constant value, construct it with
1976+// [NewBetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto].
1992type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto struct {
1977type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto struct {
1993 // Always `auto`.
1978 // Always `auto`.
1994− //
1995− // This field can be elided, and will marshal its zero value as "auto".
1996 Type constant.Auto `json:"type,required"`
1979 Type constant.Auto `json:"type,required"`
1997 paramObj
1980 paramObj
1998}
1981}
1999
1982
2000−// IsPresent returns true if the field's value is not omitted and not the JSON
2001−// "null". To check if this field is omitted, use [param.IsOmitted].
2002−func (f BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) IsPresent() bool {
2003− return !param.IsOmitted(f) && !f.IsNull()
2004−}
2005func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) MarshalJSON() (data []byte, err error) {
1983func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) MarshalJSON() (data []byte, err error) {
2006 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto
1984 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto
2007 return param.MarshalObject(r, (*shadow)(&r))
1985 return param.MarshalObject(r, (*shadow)(&r))
2008}
1986}
1987+func (r *BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) UnmarshalJSON(data []byte) error {
1988+ return apijson.UnmarshalRoot(data, r)
1989+}
2009
1990
2010// The properties Static, Type are required.
1991// The properties Static, Type are required.
2011type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic struct {
1992type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic struct {
@@ -2017,15 +1998,13 @@ type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategySta
2017 paramObj
1998 paramObj
2018}
1999}
2019
2000
2020−// IsPresent returns true if the field's value is not omitted and not the JSON
2021−// "null". To check if this field is omitted, use [param.IsOmitted].
2022−func (f BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) IsPresent() bool {
2023− return !param.IsOmitted(f) && !f.IsNull()
2024−}
2025func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) MarshalJSON() (data []byte, err error) {
2001func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) MarshalJSON() (data []byte, err error) {
2026 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic
2002 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic
2027 return param.MarshalObject(r, (*shadow)(&r))
2003 return param.MarshalObject(r, (*shadow)(&r))
2028}
2004}
2005+func (r *BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) UnmarshalJSON(data []byte) error {
2006+ return apijson.UnmarshalRoot(data, r)
2007+}
2029
2008
2030// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required.
2009// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required.
2031type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic struct {
2010type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic struct {
@@ -2039,15 +2018,13 @@ type BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategySta
2039 paramObj
2018 paramObj
2040}
2019}
2041
2020
2042−// IsPresent returns true if the field's value is not omitted and not the JSON
2043−// "null". To check if this field is omitted, use [param.IsOmitted].
2044−func (f BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) IsPresent() bool {
2045− return !param.IsOmitted(f) && !f.IsNull()
2046−}
2047func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) {
2021func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) {
2048 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic
2022 type shadow BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic
2049 return param.MarshalObject(r, (*shadow)(&r))
2023 return param.MarshalObject(r, (*shadow)(&r))
2050}
2024}
2025+func (r *BetaAssistantNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) UnmarshalJSON(data []byte) error {
2026+ return apijson.UnmarshalRoot(data, r)
2027+}
2051
2028
2052type BetaAssistantUpdateParams struct {
2029type BetaAssistantUpdateParams struct {
2053 // The description of the assistant. The maximum length is 512 characters.
2030 // The description of the assistant. The maximum length is 512 characters.
@@ -2073,7 +2050,7 @@ type BetaAssistantUpdateParams struct {
2073 //
2050 //
2074 // Keys are strings with a maximum length of 64 characters. Values are strings with
2051 // Keys are strings with a maximum length of 64 characters. Values are strings with
2075 // a maximum length of 512 characters.
2052 // a maximum length of 512 characters.
2076− Metadata shared.MetadataParam `json:"metadata,omitzero"`
2053+ Metadata shared.Metadata `json:"metadata,omitzero"`
2077 // **o-series models only**
2054 // **o-series models only**
2078 //
2055 //
2079 // Constrains effort on reasoning for
2056 // Constrains effort on reasoning for
@@ -2093,7 +2070,7 @@ type BetaAssistantUpdateParams struct {
2093 // see all of your available models, or see our
2070 // see all of your available models, or see our
2094 // [Model overview](https://platform.openai.com/docs/models) for descriptions of
2071 // [Model overview](https://platform.openai.com/docs/models) for descriptions of
2095 // them.
2072 // them.
2096− Model string `json:"model,omitzero"`
2073+ Model BetaAssistantUpdateParamsModel `json:"model,omitzero"`
2097 // Specifies the format that the model must output. Compatible with
2074 // Specifies the format that the model must output. Compatible with
2098 // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o),
2075 // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o),
2099 // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4),
2076 // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4),
@@ -2122,14 +2099,59 @@ type BetaAssistantUpdateParams struct {
2122 paramObj
2099 paramObj
2123}
2100}
2124
2101
2125−// IsPresent returns true if the field's value is not omitted and not the JSON
2126−// "null". To check if this field is omitted, use [param.IsOmitted].
2127−func (f BetaAssistantUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2128−
2129func (r BetaAssistantUpdateParams) MarshalJSON() (data []byte, err error) {
2102func (r BetaAssistantUpdateParams) MarshalJSON() (data []byte, err error) {
2130 type shadow BetaAssistantUpdateParams
2103 type shadow BetaAssistantUpdateParams
2131 return param.MarshalObject(r, (*shadow)(&r))
2104 return param.MarshalObject(r, (*shadow)(&r))
2132}
2105}
2106+func (r *BetaAssistantUpdateParams) UnmarshalJSON(data []byte) error {
2107+ return apijson.UnmarshalRoot(data, r)
2108+}
2109+
2110+// ID of the model to use. You can use the
2111+// [List models](https://platform.openai.com/docs/api-reference/models/list) API to
2112+// see all of your available models, or see our
2113+// [Model overview](https://platform.openai.com/docs/models) for descriptions of
2114+// them.
2115+type BetaAssistantUpdateParamsModel string
2116+
2117+const (
2118+ BetaAssistantUpdateParamsModelGPT4_1 BetaAssistantUpdateParamsModel = "gpt-4.1"
2119+ BetaAssistantUpdateParamsModelGPT4_1Mini BetaAssistantUpdateParamsModel = "gpt-4.1-mini"
2120+ BetaAssistantUpdateParamsModelGPT4_1Nano BetaAssistantUpdateParamsModel = "gpt-4.1-nano"
2121+ BetaAssistantUpdateParamsModelGPT4_1_2025_04_14 BetaAssistantUpdateParamsModel = "gpt-4.1-2025-04-14"
2122+ BetaAssistantUpdateParamsModelGPT4_1Mini2025_04_14 BetaAssistantUpdateParamsModel = "gpt-4.1-mini-2025-04-14"
2123+ BetaAssistantUpdateParamsModelGPT4_1Nano2025_04_14 BetaAssistantUpdateParamsModel = "gpt-4.1-nano-2025-04-14"
2124+ BetaAssistantUpdateParamsModelO3Mini BetaAssistantUpdateParamsModel = "o3-mini"
2125+ BetaAssistantUpdateParamsModelO3Mini2025_01_31 BetaAssistantUpdateParamsModel = "o3-mini-2025-01-31"
2126+ BetaAssistantUpdateParamsModelO1 BetaAssistantUpdateParamsModel = "o1"
2127+ BetaAssistantUpdateParamsModelO1_2024_12_17 BetaAssistantUpdateParamsModel = "o1-2024-12-17"
2128+ BetaAssistantUpdateParamsModelGPT4o BetaAssistantUpdateParamsModel = "gpt-4o"
2129+ BetaAssistantUpdateParamsModelGPT4o2024_11_20 BetaAssistantUpdateParamsModel = "gpt-4o-2024-11-20"
2130+ BetaAssistantUpdateParamsModelGPT4o2024_08_06 BetaAssistantUpdateParamsModel = "gpt-4o-2024-08-06"
2131+ BetaAssistantUpdateParamsModelGPT4o2024_05_13 BetaAssistantUpdateParamsModel = "gpt-4o-2024-05-13"
2132+ BetaAssistantUpdateParamsModelGPT4oMini BetaAssistantUpdateParamsModel = "gpt-4o-mini"
2133+ BetaAssistantUpdateParamsModelGPT4oMini2024_07_18 BetaAssistantUpdateParamsModel = "gpt-4o-mini-2024-07-18"
2134+ BetaAssistantUpdateParamsModelGPT4_5Preview BetaAssistantUpdateParamsModel = "gpt-4.5-preview"
2135+ BetaAssistantUpdateParamsModelGPT4_5Preview2025_02_27 BetaAssistantUpdateParamsModel = "gpt-4.5-preview-2025-02-27"
2136+ BetaAssistantUpdateParamsModelGPT4Turbo BetaAssistantUpdateParamsModel = "gpt-4-turbo"
2137+ BetaAssistantUpdateParamsModelGPT4Turbo2024_04_09 BetaAssistantUpdateParamsModel = "gpt-4-turbo-2024-04-09"
2138+ BetaAssistantUpdateParamsModelGPT4_0125Preview BetaAssistantUpdateParamsModel = "gpt-4-0125-preview"
2139+ BetaAssistantUpdateParamsModelGPT4TurboPreview BetaAssistantUpdateParamsModel = "gpt-4-turbo-preview"
2140+ BetaAssistantUpdateParamsModelGPT4_1106Preview BetaAssistantUpdateParamsModel = "gpt-4-1106-preview"
2141+ BetaAssistantUpdateParamsModelGPT4VisionPreview BetaAssistantUpdateParamsModel = "gpt-4-vision-preview"
2142+ BetaAssistantUpdateParamsModelGPT4 BetaAssistantUpdateParamsModel = "gpt-4"
2143+ BetaAssistantUpdateParamsModelGPT4_0314 BetaAssistantUpdateParamsModel = "gpt-4-0314"
2144+ BetaAssistantUpdateParamsModelGPT4_0613 BetaAssistantUpdateParamsModel = "gpt-4-0613"
2145+ BetaAssistantUpdateParamsModelGPT4_32k BetaAssistantUpdateParamsModel = "gpt-4-32k"
2146+ BetaAssistantUpdateParamsModelGPT4_32k0314 BetaAssistantUpdateParamsModel = "gpt-4-32k-0314"
2147+ BetaAssistantUpdateParamsModelGPT4_32k0613 BetaAssistantUpdateParamsModel = "gpt-4-32k-0613"
2148+ BetaAssistantUpdateParamsModelGPT3_5Turbo BetaAssistantUpdateParamsModel = "gpt-3.5-turbo"
2149+ BetaAssistantUpdateParamsModelGPT3_5Turbo16k BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-16k"
2150+ BetaAssistantUpdateParamsModelGPT3_5Turbo0613 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-0613"
2151+ BetaAssistantUpdateParamsModelGPT3_5Turbo1106 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-1106"
2152+ BetaAssistantUpdateParamsModelGPT3_5Turbo0125 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-0125"
2153+ BetaAssistantUpdateParamsModelGPT3_5Turbo16k0613 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-16k-0613"
2154+)
2133
2155
2134// A set of resources that are used by the assistant's tools. The resources are
2156// A set of resources that are used by the assistant's tools. The resources are
2135// specific to the type of tool. For example, the `code_interpreter` tool requires
2157// specific to the type of tool. For example, the `code_interpreter` tool requires
@@ -2141,15 +2163,13 @@ type BetaAssistantUpdateParamsToolResources struct {
2141 paramObj
2163 paramObj
2142}
2164}
2143
2165
2144−// IsPresent returns true if the field's value is not omitted and not the JSON
2145−// "null". To check if this field is omitted, use [param.IsOmitted].
2146−func (f BetaAssistantUpdateParamsToolResources) IsPresent() bool {
2147− return !param.IsOmitted(f) && !f.IsNull()
2148−}
2149func (r BetaAssistantUpdateParamsToolResources) MarshalJSON() (data []byte, err error) {
2166func (r BetaAssistantUpdateParamsToolResources) MarshalJSON() (data []byte, err error) {
2150 type shadow BetaAssistantUpdateParamsToolResources
2167 type shadow BetaAssistantUpdateParamsToolResources
2151 return param.MarshalObject(r, (*shadow)(&r))
2168 return param.MarshalObject(r, (*shadow)(&r))
2152}
2169}
2170+func (r *BetaAssistantUpdateParamsToolResources) UnmarshalJSON(data []byte) error {
2171+ return apijson.UnmarshalRoot(data, r)
2172+}
2153
2173
2154type BetaAssistantUpdateParamsToolResourcesCodeInterpreter struct {
2174type BetaAssistantUpdateParamsToolResourcesCodeInterpreter struct {
2155 // Overrides the list of
2175 // Overrides the list of
@@ -2160,15 +2180,13 @@ type BetaAssistantUpdateParamsToolResourcesCodeInterpreter struct {
2160 paramObj
2180 paramObj
2161}
2181}
2162
2182
2163−// IsPresent returns true if the field's value is not omitted and not the JSON
2164−// "null". To check if this field is omitted, use [param.IsOmitted].
2165−func (f BetaAssistantUpdateParamsToolResourcesCodeInterpreter) IsPresent() bool {
2166− return !param.IsOmitted(f) && !f.IsNull()
2167−}
2168func (r BetaAssistantUpdateParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
2183func (r BetaAssistantUpdateParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
2169 type shadow BetaAssistantUpdateParamsToolResourcesCodeInterpreter
2184 type shadow BetaAssistantUpdateParamsToolResourcesCodeInterpreter
2170 return param.MarshalObject(r, (*shadow)(&r))
2185 return param.MarshalObject(r, (*shadow)(&r))
2171}
2186}
2187+func (r *BetaAssistantUpdateParamsToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error {
2188+ return apijson.UnmarshalRoot(data, r)
2189+}
2172
2190
2173type BetaAssistantUpdateParamsToolResourcesFileSearch struct {
2191type BetaAssistantUpdateParamsToolResourcesFileSearch struct {
2174 // Overrides the
2192 // Overrides the
@@ -2179,15 +2197,13 @@ type BetaAssistantUpdateParamsToolResourcesFileSearch struct {
2179 paramObj
2197 paramObj
2180}
2198}
2181
2199
2182−// IsPresent returns true if the field's value is not omitted and not the JSON
2183−// "null". To check if this field is omitted, use [param.IsOmitted].
2184−func (f BetaAssistantUpdateParamsToolResourcesFileSearch) IsPresent() bool {
2185− return !param.IsOmitted(f) && !f.IsNull()
2186−}
2187func (r BetaAssistantUpdateParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
2200func (r BetaAssistantUpdateParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
2188 type shadow BetaAssistantUpdateParamsToolResourcesFileSearch
2201 type shadow BetaAssistantUpdateParamsToolResourcesFileSearch
2189 return param.MarshalObject(r, (*shadow)(&r))
2202 return param.MarshalObject(r, (*shadow)(&r))
2190}
2203}
2204+func (r *BetaAssistantUpdateParamsToolResourcesFileSearch) UnmarshalJSON(data []byte) error {
2205+ return apijson.UnmarshalRoot(data, r)
2206+}
2191
2207
2192type BetaAssistantListParams struct {
2208type BetaAssistantListParams struct {
2193 // A cursor for use in pagination. `after` is an object ID that defines your place
2209 // A cursor for use in pagination. `after` is an object ID that defines your place
@@ -2211,13 +2227,9 @@ type BetaAssistantListParams struct {
2211 paramObj
2227 paramObj
2212}
2228}
2213
2229
2214−// IsPresent returns true if the field's value is not omitted and not the JSON
2215−// "null". To check if this field is omitted, use [param.IsOmitted].
2216−func (f BetaAssistantListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2217−
2218// URLQuery serializes [BetaAssistantListParams]'s query parameters as
2230// URLQuery serializes [BetaAssistantListParams]'s query parameters as
2219// `url.Values`.
2231// `url.Values`.
2220−func (r BetaAssistantListParams) URLQuery() (v url.Values) {
2232+func (r BetaAssistantListParams) URLQuery() (v url.Values, err error) {
2221 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
2233 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
2222 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
2234 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
2223 NestedFormat: apiquery.NestedQueryFormatBrackets,
2235 NestedFormat: apiquery.NestedQueryFormatBrackets,
vendor/github.com/openai/openai-go/betathread.go+257−403
@@ -8,17 +8,15 @@ import (
8 "errors"
8 "errors"
9 "fmt"
9 "fmt"
10 "net/http"
10 "net/http"
11− "reflect"
12
11
13 "github.com/openai/openai-go/internal/apijson"
12 "github.com/openai/openai-go/internal/apijson"
14 "github.com/openai/openai-go/internal/requestconfig"
13 "github.com/openai/openai-go/internal/requestconfig"
15 "github.com/openai/openai-go/option"
14 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/packages/param"
15 "github.com/openai/openai-go/packages/param"
17− "github.com/openai/openai-go/packages/resp"
16+ "github.com/openai/openai-go/packages/respjson"
18 "github.com/openai/openai-go/packages/ssestream"
17 "github.com/openai/openai-go/packages/ssestream"
19 "github.com/openai/openai-go/shared"
18 "github.com/openai/openai-go/shared"
20 "github.com/openai/openai-go/shared/constant"
19 "github.com/openai/openai-go/shared/constant"
21− "github.com/tidwall/gjson"
22)
20)
23
21
24// BetaThreadService contains methods and other services that help with interacting
22// BetaThreadService contains methods and other services that help with interacting
@@ -27,9 +25,13 @@ import (
27// Note, unlike clients, this service does not read variables from the environment
25// Note, unlike clients, this service does not read variables from the environment
28// automatically. You should not instantiate this service directly, and instead use
26// automatically. You should not instantiate this service directly, and instead use
29// the [NewBetaThreadService] method instead.
27// the [NewBetaThreadService] method instead.
28+//
29+// Deprecated: The Assistants API is deprecated in favor of the Responses API
30type BetaThreadService struct {
30type BetaThreadService struct {
31− Options []option.RequestOption
31+ Options []option.RequestOption
32+ // Deprecated: The Assistants API is deprecated in favor of the Responses API
32− Runs BetaThreadRunService
33+ Runs BetaThreadRunService
34+ // Deprecated: The Assistants API is deprecated in favor of the Responses API
33 Messages BetaThreadMessageService
35 Messages BetaThreadMessageService
34}
36}
35
37
@@ -45,6 +47,8 @@ func NewBetaThreadService(opts ...option.RequestOption) (r BetaThreadService) {
45}
47}
46
48
47// Create a thread.
49// Create a thread.
50+//
51+// Deprecated: The Assistants API is deprecated in favor of the Responses API
48func (r *BetaThreadService) New(ctx context.Context, body BetaThreadNewParams, opts ...option.RequestOption) (res *Thread, err error) {
52func (r *BetaThreadService) New(ctx context.Context, body BetaThreadNewParams, opts ...option.RequestOption) (res *Thread, err error) {
49 opts = append(r.Options[:], opts...)
53 opts = append(r.Options[:], opts...)
50 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
54 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -53,16 +57,9 @@ func (r *BetaThreadService) New(ctx context.Context, body BetaThreadNewParams, o
53 return
57 return
54}
58}
55
59
56−// Create a thread and run it in one request. Poll the API until the run is complete.
57−func (r *BetaThreadService) NewAndRunPoll(ctx context.Context, body BetaThreadNewAndRunParams, pollIntervalMs int, opts ...option.RequestOption) (res *Run, err error) {
58− run, err := r.NewAndRun(ctx, body, opts...)
59− if err != nil {
60− return nil, err
61− }
62− return r.Runs.PollStatus(ctx, run.ThreadID, run.ID, pollIntervalMs, opts...)
63−}
64−
65// Retrieves a thread.
60// Retrieves a thread.
61+//
62+// Deprecated: The Assistants API is deprecated in favor of the Responses API
66func (r *BetaThreadService) Get(ctx context.Context, threadID string, opts ...option.RequestOption) (res *Thread, err error) {
63func (r *BetaThreadService) Get(ctx context.Context, threadID string, opts ...option.RequestOption) (res *Thread, err error) {
67 opts = append(r.Options[:], opts...)
64 opts = append(r.Options[:], opts...)
68 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
65 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -76,6 +73,8 @@ func (r *BetaThreadService) Get(ctx context.Context, threadID string, opts ...op
76}
73}
77
74
78// Modifies a thread.
75// Modifies a thread.
76+//
77+// Deprecated: The Assistants API is deprecated in favor of the Responses API
79func (r *BetaThreadService) Update(ctx context.Context, threadID string, body BetaThreadUpdateParams, opts ...option.RequestOption) (res *Thread, err error) {
78func (r *BetaThreadService) Update(ctx context.Context, threadID string, body BetaThreadUpdateParams, opts ...option.RequestOption) (res *Thread, err error) {
80 opts = append(r.Options[:], opts...)
79 opts = append(r.Options[:], opts...)
81 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
80 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -89,6 +88,8 @@ func (r *BetaThreadService) Update(ctx context.Context, threadID string, body Be
89}
88}
90
89
91// Delete a thread.
90// Delete a thread.
91+//
92+// Deprecated: The Assistants API is deprecated in favor of the Responses API
92func (r *BetaThreadService) Delete(ctx context.Context, threadID string, opts ...option.RequestOption) (res *ThreadDeleted, err error) {
93func (r *BetaThreadService) Delete(ctx context.Context, threadID string, opts ...option.RequestOption) (res *ThreadDeleted, err error) {
93 opts = append(r.Options[:], opts...)
94 opts = append(r.Options[:], opts...)
94 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
95 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -102,6 +103,8 @@ func (r *BetaThreadService) Delete(ctx context.Context, threadID string, opts ..
102}
103}
103
104
104// Create a thread and run it in one request.
105// Create a thread and run it in one request.
106+//
107+// Deprecated: The Assistants API is deprecated in favor of the Responses API
105func (r *BetaThreadService) NewAndRun(ctx context.Context, body BetaThreadNewAndRunParams, opts ...option.RequestOption) (res *Run, err error) {
108func (r *BetaThreadService) NewAndRun(ctx context.Context, body BetaThreadNewAndRunParams, opts ...option.RequestOption) (res *Run, err error) {
106 opts = append(r.Options[:], opts...)
109 opts = append(r.Options[:], opts...)
107 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
110 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -111,6 +114,8 @@ func (r *BetaThreadService) NewAndRun(ctx context.Context, body BetaThreadNewAnd
111}
114}
112
115
113// Create a thread and run it in one request.
116// Create a thread and run it in one request.
117+//
118+// Deprecated: The Assistants API is deprecated in favor of the Responses API
114func (r *BetaThreadService) NewAndRunStreaming(ctx context.Context, body BetaThreadNewAndRunParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) {
119func (r *BetaThreadService) NewAndRunStreaming(ctx context.Context, body BetaThreadNewAndRunParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) {
115 var (
120 var (
116 raw *http.Response
121 raw *http.Response
@@ -139,9 +144,9 @@ type AssistantResponseFormatOptionUnion struct {
139 // This field is from variant [shared.ResponseFormatJSONSchema].
144 // This field is from variant [shared.ResponseFormatJSONSchema].
140 JSONSchema shared.ResponseFormatJSONSchemaJSONSchema `json:"json_schema"`
145 JSONSchema shared.ResponseFormatJSONSchemaJSONSchema `json:"json_schema"`
141 JSON struct {
146 JSON struct {
142− OfAuto resp.Field
147+ OfAuto respjson.Field
143− Type resp.Field
148+ Type respjson.Field
144− JSONSchema resp.Field
149+ JSONSchema respjson.Field
145 raw string
150 raw string
146 } `json:"-"`
151 } `json:"-"`
147}
152}
@@ -178,9 +183,9 @@ func (r *AssistantResponseFormatOptionUnion) UnmarshalJSON(data []byte) error {
178//
183//
179// Warning: the fields of the param type will not be present. ToParam should only
184// Warning: the fields of the param type will not be present. ToParam should only
180// be used at the last possible moment before sending a request. Test for this with
185// be used at the last possible moment before sending a request. Test for this with
181−// AssistantResponseFormatOptionUnionParam.IsOverridden()
186+// AssistantResponseFormatOptionUnionParam.Overrides()
182func (r AssistantResponseFormatOptionUnion) ToParam() AssistantResponseFormatOptionUnionParam {
187func (r AssistantResponseFormatOptionUnion) ToParam() AssistantResponseFormatOptionUnionParam {
183− return param.OverrideObj[AssistantResponseFormatOptionUnionParam](r.RawJSON())
188+ return param.Override[AssistantResponseFormatOptionUnionParam](json.RawMessage(r.RawJSON()))
184}
189}
185
190
186func AssistantResponseFormatOptionParamOfAuto() AssistantResponseFormatOptionUnionParam {
191func AssistantResponseFormatOptionParamOfAuto() AssistantResponseFormatOptionUnionParam {
@@ -197,8 +202,7 @@ func AssistantResponseFormatOptionParamOfJSONSchema(jsonSchema shared.ResponseFo
197//
202//
198// Use [param.IsOmitted] to confirm if a field is set.
203// Use [param.IsOmitted] to confirm if a field is set.
199type AssistantResponseFormatOptionUnionParam struct {
204type AssistantResponseFormatOptionUnionParam struct {
200− // Construct this variant with constant.New[constant.Auto]() Check if union is this
205+ // Construct this variant with constant.ValueOf[constant.Auto]()
201− // variant with !param.IsOmitted(union.OfAuto)
202 OfAuto constant.Auto `json:",omitzero,inline"`
206 OfAuto constant.Auto `json:",omitzero,inline"`
203 OfText *shared.ResponseFormatTextParam `json:",omitzero,inline"`
207 OfText *shared.ResponseFormatTextParam `json:",omitzero,inline"`
204 OfJSONObject *shared.ResponseFormatJSONObjectParam `json:",omitzero,inline"`
208 OfJSONObject *shared.ResponseFormatJSONObjectParam `json:",omitzero,inline"`
@@ -206,13 +210,11 @@ type AssistantResponseFormatOptionUnionParam struct {
206 paramUnion
210 paramUnion
207}
211}
208
212
209−// IsPresent returns true if the field's value is not omitted and not the JSON
210−// "null". To check if this field is omitted, use [param.IsOmitted].
211−func (u AssistantResponseFormatOptionUnionParam) IsPresent() bool {
212− return !param.IsOmitted(u) && !u.IsNull()
213−}
214func (u AssistantResponseFormatOptionUnionParam) MarshalJSON() ([]byte, error) {
213func (u AssistantResponseFormatOptionUnionParam) MarshalJSON() ([]byte, error) {
215− return param.MarshalUnion[AssistantResponseFormatOptionUnionParam](u.OfAuto, u.OfText, u.OfJSONObject, u.OfJSONSchema)
214+ return param.MarshalUnion(u, u.OfAuto, u.OfText, u.OfJSONObject, u.OfJSONSchema)
215+}
216+func (u *AssistantResponseFormatOptionUnionParam) UnmarshalJSON(data []byte) error {
217+ return apijson.UnmarshalRoot(data, u)
216}
218}
217
219
218func (u *AssistantResponseFormatOptionUnionParam) asAny() any {
220func (u *AssistantResponseFormatOptionUnionParam) asAny() any {
@@ -256,12 +258,11 @@ type AssistantToolChoice struct {
256 // Any of "function", "code_interpreter", "file_search".
258 // Any of "function", "code_interpreter", "file_search".
257 Type AssistantToolChoiceType `json:"type,required"`
259 Type AssistantToolChoiceType `json:"type,required"`
258 Function AssistantToolChoiceFunction `json:"function"`
260 Function AssistantToolChoiceFunction `json:"function"`
259− // Metadata for the response, check the presence of optional fields with the
261+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
260− // [resp.Field.IsPresent] method.
261 JSON struct {
262 JSON struct {
262− Type resp.Field
263+ Type respjson.Field
263− Function resp.Field
264+ Function respjson.Field
264− ExtraFields map[string]resp.Field
265+ ExtraFields map[string]respjson.Field
265 raw string
266 raw string
266 } `json:"-"`
267 } `json:"-"`
267}
268}
@@ -276,9 +277,9 @@ func (r *AssistantToolChoice) UnmarshalJSON(data []byte) error {
276//
277//
277// Warning: the fields of the param type will not be present. ToParam should only
278// Warning: the fields of the param type will not be present. ToParam should only
278// be used at the last possible moment before sending a request. Test for this with
279// be used at the last possible moment before sending a request. Test for this with
279−// AssistantToolChoiceParam.IsOverridden()
280+// AssistantToolChoiceParam.Overrides()
280func (r AssistantToolChoice) ToParam() AssistantToolChoiceParam {
281func (r AssistantToolChoice) ToParam() AssistantToolChoiceParam {
281− return param.OverrideObj[AssistantToolChoiceParam](r.RawJSON())
282+ return param.Override[AssistantToolChoiceParam](json.RawMessage(r.RawJSON()))
282}
283}
283
284
284// The type of the tool. If type is `function`, the function name must be set
285// The type of the tool. If type is `function`, the function name must be set
@@ -303,22 +304,21 @@ type AssistantToolChoiceParam struct {
303 paramObj
304 paramObj
304}
305}
305
306
306−// IsPresent returns true if the field's value is not omitted and not the JSON
307−// "null". To check if this field is omitted, use [param.IsOmitted].
308−func (f AssistantToolChoiceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
309func (r AssistantToolChoiceParam) MarshalJSON() (data []byte, err error) {
307func (r AssistantToolChoiceParam) MarshalJSON() (data []byte, err error) {
310 type shadow AssistantToolChoiceParam
308 type shadow AssistantToolChoiceParam
311 return param.MarshalObject(r, (*shadow)(&r))
309 return param.MarshalObject(r, (*shadow)(&r))
312}
310}
311+func (r *AssistantToolChoiceParam) UnmarshalJSON(data []byte) error {
312+ return apijson.UnmarshalRoot(data, r)
313+}
313
314
314type AssistantToolChoiceFunction struct {
315type AssistantToolChoiceFunction struct {
315 // The name of the function to call.
316 // The name of the function to call.
316 Name string `json:"name,required"`
317 Name string `json:"name,required"`
317− // Metadata for the response, check the presence of optional fields with the
318+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
318− // [resp.Field.IsPresent] method.
319 JSON struct {
319 JSON struct {
320− Name resp.Field
320+ Name respjson.Field
321− ExtraFields map[string]resp.Field
321+ ExtraFields map[string]respjson.Field
322 raw string
322 raw string
323 } `json:"-"`
323 } `json:"-"`
324}
324}
@@ -334,9 +334,9 @@ func (r *AssistantToolChoiceFunction) UnmarshalJSON(data []byte) error {
334//
334//
335// Warning: the fields of the param type will not be present. ToParam should only
335// Warning: the fields of the param type will not be present. ToParam should only
336// be used at the last possible moment before sending a request. Test for this with
336// be used at the last possible moment before sending a request. Test for this with
337−// AssistantToolChoiceFunctionParam.IsOverridden()
337+// AssistantToolChoiceFunctionParam.Overrides()
338func (r AssistantToolChoiceFunction) ToParam() AssistantToolChoiceFunctionParam {
338func (r AssistantToolChoiceFunction) ToParam() AssistantToolChoiceFunctionParam {
339− return param.OverrideObj[AssistantToolChoiceFunctionParam](r.RawJSON())
339+ return param.Override[AssistantToolChoiceFunctionParam](json.RawMessage(r.RawJSON()))
340}
340}
341
341
342// The property Name is required.
342// The property Name is required.
@@ -346,13 +346,13 @@ type AssistantToolChoiceFunctionParam struct {
346 paramObj
346 paramObj
347}
347}
348
348
349−// IsPresent returns true if the field's value is not omitted and not the JSON
350−// "null". To check if this field is omitted, use [param.IsOmitted].
351−func (f AssistantToolChoiceFunctionParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
352func (r AssistantToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) {
349func (r AssistantToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) {
353 type shadow AssistantToolChoiceFunctionParam
350 type shadow AssistantToolChoiceFunctionParam
354 return param.MarshalObject(r, (*shadow)(&r))
351 return param.MarshalObject(r, (*shadow)(&r))
355}
352}
353+func (r *AssistantToolChoiceFunctionParam) UnmarshalJSON(data []byte) error {
354+ return apijson.UnmarshalRoot(data, r)
355+}
356
356
357// AssistantToolChoiceOptionUnion contains all possible properties and values from
357// AssistantToolChoiceOptionUnion contains all possible properties and values from
358// [string], [AssistantToolChoice].
358// [string], [AssistantToolChoice].
@@ -369,9 +369,9 @@ type AssistantToolChoiceOptionUnion struct {
369 // This field is from variant [AssistantToolChoice].
369 // This field is from variant [AssistantToolChoice].
370 Function AssistantToolChoiceFunction `json:"function"`
370 Function AssistantToolChoiceFunction `json:"function"`
371 JSON struct {
371 JSON struct {
372− OfAuto resp.Field
372+ OfAuto respjson.Field
373− Type resp.Field
373+ Type respjson.Field
374− Function resp.Field
374+ Function respjson.Field
375 raw string
375 raw string
376 } `json:"-"`
376 } `json:"-"`
377}
377}
@@ -398,11 +398,23 @@ func (r *AssistantToolChoiceOptionUnion) UnmarshalJSON(data []byte) error {
398//
398//
399// Warning: the fields of the param type will not be present. ToParam should only
399// Warning: the fields of the param type will not be present. ToParam should only
400// be used at the last possible moment before sending a request. Test for this with
400// be used at the last possible moment before sending a request. Test for this with
401−// AssistantToolChoiceOptionUnionParam.IsOverridden()
401+// AssistantToolChoiceOptionUnionParam.Overrides()
402func (r AssistantToolChoiceOptionUnion) ToParam() AssistantToolChoiceOptionUnionParam {
402func (r AssistantToolChoiceOptionUnion) ToParam() AssistantToolChoiceOptionUnionParam {
403− return param.OverrideObj[AssistantToolChoiceOptionUnionParam](r.RawJSON())
403+ return param.Override[AssistantToolChoiceOptionUnionParam](json.RawMessage(r.RawJSON()))
404}
404}
405
405
406+// `none` means the model will not call any tools and instead generates a message.
407+// `auto` means the model can pick between generating a message or calling one or
408+// more tools. `required` means the model must call one or more tools before
409+// responding to the user.
410+type AssistantToolChoiceOptionAuto string
411+
412+const (
413+ AssistantToolChoiceOptionAutoNone AssistantToolChoiceOptionAuto = "none"
414+ AssistantToolChoiceOptionAutoAuto AssistantToolChoiceOptionAuto = "auto"
415+ AssistantToolChoiceOptionAutoRequired AssistantToolChoiceOptionAuto = "required"
416+)
417+
406func AssistantToolChoiceOptionParamOfAssistantToolChoice(type_ AssistantToolChoiceType) AssistantToolChoiceOptionUnionParam {
418func AssistantToolChoiceOptionParamOfAssistantToolChoice(type_ AssistantToolChoiceType) AssistantToolChoiceOptionUnionParam {
407 var variant AssistantToolChoiceParam
419 var variant AssistantToolChoiceParam
408 variant.Type = type_
420 variant.Type = type_
@@ -419,13 +431,11 @@ type AssistantToolChoiceOptionUnionParam struct {
419 paramUnion
431 paramUnion
420}
432}
421
433
422−// IsPresent returns true if the field's value is not omitted and not the JSON
423−// "null". To check if this field is omitted, use [param.IsOmitted].
424−func (u AssistantToolChoiceOptionUnionParam) IsPresent() bool {
425− return !param.IsOmitted(u) && !u.IsNull()
426−}
427func (u AssistantToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) {
434func (u AssistantToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) {
435+ return param.MarshalUnion(u, u.OfAuto, u.OfAssistantToolChoice)
436+}
428− return param.MarshalUnion[AssistantToolChoiceOptionUnionParam](u.OfAuto, u.OfAssistantToolChoice)
437+func (u *AssistantToolChoiceOptionUnionParam) UnmarshalJSON(data []byte) error {
438+ return apijson.UnmarshalRoot(data, u)
429}
439}
430
440
431func (u *AssistantToolChoiceOptionUnionParam) asAny() any {
441func (u *AssistantToolChoiceOptionUnionParam) asAny() any {
@@ -437,22 +447,6 @@ func (u *AssistantToolChoiceOptionUnionParam) asAny() any {
437 return nil
447 return nil
438}
448}
439
449
440−// Returns a pointer to the underlying variant's property, if present.
441−func (u AssistantToolChoiceOptionUnionParam) GetType() *string {
442− if vt := u.OfAssistantToolChoice; vt != nil {
443− return (*string)(&vt.Type)
444− }
445− return nil
446−}
447−
448−// Returns a pointer to the underlying variant's property, if present.
449−func (u AssistantToolChoiceOptionUnionParam) GetFunction() *AssistantToolChoiceFunctionParam {
450− if vt := u.OfAssistantToolChoice; vt != nil {
451− return &vt.Function
452− }
453− return nil
454−}
455−
456// Represents a thread that contains
450// Represents a thread that contains
457// [messages](https://platform.openai.com/docs/api-reference/messages).
451// [messages](https://platform.openai.com/docs/api-reference/messages).
458type Thread struct {
452type Thread struct {
@@ -474,15 +468,14 @@ type Thread struct {
474 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
468 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
475 // tool requires a list of vector store IDs.
469 // tool requires a list of vector store IDs.
476 ToolResources ThreadToolResources `json:"tool_resources,required"`
470 ToolResources ThreadToolResources `json:"tool_resources,required"`
477− // Metadata for the response, check the presence of optional fields with the
471+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
478− // [resp.Field.IsPresent] method.
479 JSON struct {
472 JSON struct {
480− ID resp.Field
473+ ID respjson.Field
481− CreatedAt resp.Field
474+ CreatedAt respjson.Field
482− Metadata resp.Field
475+ Metadata respjson.Field
483− Object resp.Field
476+ Object respjson.Field
484− ToolResources resp.Field
477+ ToolResources respjson.Field
485− ExtraFields map[string]resp.Field
478+ ExtraFields map[string]respjson.Field
486 raw string
479 raw string
487 } `json:"-"`
480 } `json:"-"`
488}
481}
@@ -500,12 +493,11 @@ func (r *Thread) UnmarshalJSON(data []byte) error {
500type ThreadToolResources struct {
493type ThreadToolResources struct {
501 CodeInterpreter ThreadToolResourcesCodeInterpreter `json:"code_interpreter"`
494 CodeInterpreter ThreadToolResourcesCodeInterpreter `json:"code_interpreter"`
502 FileSearch ThreadToolResourcesFileSearch `json:"file_search"`
495 FileSearch ThreadToolResourcesFileSearch `json:"file_search"`
503− // Metadata for the response, check the presence of optional fields with the
496+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
504− // [resp.Field.IsPresent] method.
505 JSON struct {
497 JSON struct {
506− CodeInterpreter resp.Field
498+ CodeInterpreter respjson.Field
507− FileSearch resp.Field
499+ FileSearch respjson.Field
508− ExtraFields map[string]resp.Field
500+ ExtraFields map[string]respjson.Field
509 raw string
501 raw string
510 } `json:"-"`
502 } `json:"-"`
511}
503}
@@ -521,11 +513,10 @@ type ThreadToolResourcesCodeInterpreter struct {
521 // available to the `code_interpreter` tool. There can be a maximum of 20 files
513 // available to the `code_interpreter` tool. There can be a maximum of 20 files
522 // associated with the tool.
514 // associated with the tool.
523 FileIDs []string `json:"file_ids"`
515 FileIDs []string `json:"file_ids"`
524− // Metadata for the response, check the presence of optional fields with the
516+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
525− // [resp.Field.IsPresent] method.
526 JSON struct {
517 JSON struct {
527− FileIDs resp.Field
518+ FileIDs respjson.Field
528− ExtraFields map[string]resp.Field
519+ ExtraFields map[string]respjson.Field
529 raw string
520 raw string
530 } `json:"-"`
521 } `json:"-"`
531}
522}
@@ -542,11 +533,10 @@ type ThreadToolResourcesFileSearch struct {
542 // attached to this thread. There can be a maximum of 1 vector store attached to
533 // attached to this thread. There can be a maximum of 1 vector store attached to
543 // the thread.
534 // the thread.
544 VectorStoreIDs []string `json:"vector_store_ids"`
535 VectorStoreIDs []string `json:"vector_store_ids"`
545− // Metadata for the response, check the presence of optional fields with the
536+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
546− // [resp.Field.IsPresent] method.
547 JSON struct {
537 JSON struct {
548− VectorStoreIDs resp.Field
538+ VectorStoreIDs respjson.Field
549− ExtraFields map[string]resp.Field
539+ ExtraFields map[string]respjson.Field
550 raw string
540 raw string
551 } `json:"-"`
541 } `json:"-"`
552}
542}
@@ -561,13 +551,12 @@ type ThreadDeleted struct {
561 ID string `json:"id,required"`
551 ID string `json:"id,required"`
562 Deleted bool `json:"deleted,required"`
552 Deleted bool `json:"deleted,required"`
563 Object constant.ThreadDeleted `json:"object,required"`
553 Object constant.ThreadDeleted `json:"object,required"`
564− // Metadata for the response, check the presence of optional fields with the
554+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
565− // [resp.Field.IsPresent] method.
566 JSON struct {
555 JSON struct {
567− ID resp.Field
556+ ID respjson.Field
568− Deleted resp.Field
557+ Deleted respjson.Field
569− Object resp.Field
558+ Object respjson.Field
570− ExtraFields map[string]resp.Field
559+ ExtraFields map[string]respjson.Field
571 raw string
560 raw string
572 } `json:"-"`
561 } `json:"-"`
573}
562}
@@ -585,7 +574,7 @@ type BetaThreadNewParams struct {
585 //
574 //
586 // Keys are strings with a maximum length of 64 characters. Values are strings with
575 // Keys are strings with a maximum length of 64 characters. Values are strings with
587 // a maximum length of 512 characters.
576 // a maximum length of 512 characters.
588− Metadata shared.MetadataParam `json:"metadata,omitzero"`
577+ Metadata shared.Metadata `json:"metadata,omitzero"`
589 // A set of resources that are made available to the assistant's tools in this
578 // A set of resources that are made available to the assistant's tools in this
590 // thread. The resources are specific to the type of tool. For example, the
579 // thread. The resources are specific to the type of tool. For example, the
591 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
580 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
@@ -597,14 +586,13 @@ type BetaThreadNewParams struct {
597 paramObj
586 paramObj
598}
587}
599
588
600−// IsPresent returns true if the field's value is not omitted and not the JSON
601−// "null". To check if this field is omitted, use [param.IsOmitted].
602−func (f BetaThreadNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
603−
604func (r BetaThreadNewParams) MarshalJSON() (data []byte, err error) {
589func (r BetaThreadNewParams) MarshalJSON() (data []byte, err error) {
605 type shadow BetaThreadNewParams
590 type shadow BetaThreadNewParams
606 return param.MarshalObject(r, (*shadow)(&r))
591 return param.MarshalObject(r, (*shadow)(&r))
607}
592}
593+func (r *BetaThreadNewParams) UnmarshalJSON(data []byte) error {
594+ return apijson.UnmarshalRoot(data, r)
595+}
608
596
609// The properties Content, Role are required.
597// The properties Content, Role are required.
610type BetaThreadNewParamsMessage struct {
598type BetaThreadNewParamsMessage struct {
@@ -627,21 +615,21 @@ type BetaThreadNewParamsMessage struct {
627 //
615 //
628 // Keys are strings with a maximum length of 64 characters. Values are strings with
616 // Keys are strings with a maximum length of 64 characters. Values are strings with
629 // a maximum length of 512 characters.
617 // a maximum length of 512 characters.
630− Metadata shared.MetadataParam `json:"metadata,omitzero"`
618+ Metadata shared.Metadata `json:"metadata,omitzero"`
631 paramObj
619 paramObj
632}
620}
633
621
634−// IsPresent returns true if the field's value is not omitted and not the JSON
635−// "null". To check if this field is omitted, use [param.IsOmitted].
636−func (f BetaThreadNewParamsMessage) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
637func (r BetaThreadNewParamsMessage) MarshalJSON() (data []byte, err error) {
622func (r BetaThreadNewParamsMessage) MarshalJSON() (data []byte, err error) {
638 type shadow BetaThreadNewParamsMessage
623 type shadow BetaThreadNewParamsMessage
639 return param.MarshalObject(r, (*shadow)(&r))
624 return param.MarshalObject(r, (*shadow)(&r))
640}
625}
626+func (r *BetaThreadNewParamsMessage) UnmarshalJSON(data []byte) error {
627+ return apijson.UnmarshalRoot(data, r)
628+}
641
629
642func init() {
630func init() {
643 apijson.RegisterFieldValidator[BetaThreadNewParamsMessage](
631 apijson.RegisterFieldValidator[BetaThreadNewParamsMessage](
644− "Role", false, "user", "assistant",
632+ "role", "user", "assistant",
645 )
633 )
646}
634}
647
635
@@ -654,13 +642,11 @@ type BetaThreadNewParamsMessageContentUnion struct {
654 paramUnion
642 paramUnion
655}
643}
656
644
657−// IsPresent returns true if the field's value is not omitted and not the JSON
658−// "null". To check if this field is omitted, use [param.IsOmitted].
659−func (u BetaThreadNewParamsMessageContentUnion) IsPresent() bool {
660− return !param.IsOmitted(u) && !u.IsNull()
661−}
662func (u BetaThreadNewParamsMessageContentUnion) MarshalJSON() ([]byte, error) {
645func (u BetaThreadNewParamsMessageContentUnion) MarshalJSON() ([]byte, error) {
646+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
647+}
663− return param.MarshalUnion[BetaThreadNewParamsMessageContentUnion](u.OfString, u.OfArrayOfContentParts)
648+func (u *BetaThreadNewParamsMessageContentUnion) UnmarshalJSON(data []byte) error {
649+ return apijson.UnmarshalRoot(data, u)
664}
650}
665
651
666func (u *BetaThreadNewParamsMessageContentUnion) asAny() any {
652func (u *BetaThreadNewParamsMessageContentUnion) asAny() any {
@@ -680,15 +666,13 @@ type BetaThreadNewParamsMessageAttachment struct {
680 paramObj
666 paramObj
681}
667}
682
668
683−// IsPresent returns true if the field's value is not omitted and not the JSON
684−// "null". To check if this field is omitted, use [param.IsOmitted].
685−func (f BetaThreadNewParamsMessageAttachment) IsPresent() bool {
686− return !param.IsOmitted(f) && !f.IsNull()
687−}
688func (r BetaThreadNewParamsMessageAttachment) MarshalJSON() (data []byte, err error) {
669func (r BetaThreadNewParamsMessageAttachment) MarshalJSON() (data []byte, err error) {
689 type shadow BetaThreadNewParamsMessageAttachment
670 type shadow BetaThreadNewParamsMessageAttachment
690 return param.MarshalObject(r, (*shadow)(&r))
671 return param.MarshalObject(r, (*shadow)(&r))
691}
672}
673+func (r *BetaThreadNewParamsMessageAttachment) UnmarshalJSON(data []byte) error {
674+ return apijson.UnmarshalRoot(data, r)
675+}
692
676
693// Only one field can be non-zero.
677// Only one field can be non-zero.
694//
678//
@@ -699,13 +683,11 @@ type BetaThreadNewParamsMessageAttachmentToolUnion struct {
699 paramUnion
683 paramUnion
700}
684}
701
685
702−// IsPresent returns true if the field's value is not omitted and not the JSON
703−// "null". To check if this field is omitted, use [param.IsOmitted].
704−func (u BetaThreadNewParamsMessageAttachmentToolUnion) IsPresent() bool {
705− return !param.IsOmitted(u) && !u.IsNull()
706−}
707func (u BetaThreadNewParamsMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) {
686func (u BetaThreadNewParamsMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) {
687+ return param.MarshalUnion(u, u.OfCodeInterpreter, u.OfFileSearch)
688+}
708− return param.MarshalUnion[BetaThreadNewParamsMessageAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch)
689+func (u *BetaThreadNewParamsMessageAttachmentToolUnion) UnmarshalJSON(data []byte) error {
690+ return apijson.UnmarshalRoot(data, u)
709}
691}
710
692
711func (u *BetaThreadNewParamsMessageAttachmentToolUnion) asAny() any {
693func (u *BetaThreadNewParamsMessageAttachmentToolUnion) asAny() any {
@@ -730,37 +712,32 @@ func (u BetaThreadNewParamsMessageAttachmentToolUnion) GetType() *string {
730func init() {
712func init() {
731 apijson.RegisterUnion[BetaThreadNewParamsMessageAttachmentToolUnion](
713 apijson.RegisterUnion[BetaThreadNewParamsMessageAttachmentToolUnion](
732 "type",
714 "type",
733− apijson.UnionVariant{
734− TypeFilter: gjson.JSON,
735− Type: reflect.TypeOf(CodeInterpreterToolParam{}),
715+ apijson.Discriminator[CodeInterpreterToolParam]("code_interpreter"),
736− DiscriminatorValue: "code_interpreter",
737− },
738− apijson.UnionVariant{
739− TypeFilter: gjson.JSON,
740− Type: reflect.TypeOf(BetaThreadNewParamsMessageAttachmentToolFileSearch{}),
716+ apijson.Discriminator[BetaThreadNewParamsMessageAttachmentToolFileSearch]("file_search"),
741− DiscriminatorValue: "file_search",
742− },
743 )
717 )
744}
718}
745
719
746−// The property Type is required.
720+func NewBetaThreadNewParamsMessageAttachmentToolFileSearch() BetaThreadNewParamsMessageAttachmentToolFileSearch {
721+ return BetaThreadNewParamsMessageAttachmentToolFileSearch{
722+ Type: "file_search",
723+ }
724+}
725+
726+// This struct has a constant value, construct it with
727+// [NewBetaThreadNewParamsMessageAttachmentToolFileSearch].
747type BetaThreadNewParamsMessageAttachmentToolFileSearch struct {
728type BetaThreadNewParamsMessageAttachmentToolFileSearch struct {
748 // The type of tool being defined: `file_search`
729 // The type of tool being defined: `file_search`
749− //
750− // This field can be elided, and will marshal its zero value as "file_search".
751 Type constant.FileSearch `json:"type,required"`
730 Type constant.FileSearch `json:"type,required"`
752 paramObj
731 paramObj
753}
732}
754
733
755−// IsPresent returns true if the field's value is not omitted and not the JSON
756−// "null". To check if this field is omitted, use [param.IsOmitted].
757−func (f BetaThreadNewParamsMessageAttachmentToolFileSearch) IsPresent() bool {
758− return !param.IsOmitted(f) && !f.IsNull()
759−}
760func (r BetaThreadNewParamsMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
734func (r BetaThreadNewParamsMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
761 type shadow BetaThreadNewParamsMessageAttachmentToolFileSearch
735 type shadow BetaThreadNewParamsMessageAttachmentToolFileSearch
762 return param.MarshalObject(r, (*shadow)(&r))
736 return param.MarshalObject(r, (*shadow)(&r))
763}
737}
738+func (r *BetaThreadNewParamsMessageAttachmentToolFileSearch) UnmarshalJSON(data []byte) error {
739+ return apijson.UnmarshalRoot(data, r)
740+}
764
741
765// A set of resources that are made available to the assistant's tools in this
742// A set of resources that are made available to the assistant's tools in this
766// thread. The resources are specific to the type of tool. For example, the
743// thread. The resources are specific to the type of tool. For example, the
@@ -772,13 +749,13 @@ type BetaThreadNewParamsToolResources struct {
772 paramObj
749 paramObj
773}
750}
774
751
775−// IsPresent returns true if the field's value is not omitted and not the JSON
776−// "null". To check if this field is omitted, use [param.IsOmitted].
777−func (f BetaThreadNewParamsToolResources) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
778func (r BetaThreadNewParamsToolResources) MarshalJSON() (data []byte, err error) {
752func (r BetaThreadNewParamsToolResources) MarshalJSON() (data []byte, err error) {
779 type shadow BetaThreadNewParamsToolResources
753 type shadow BetaThreadNewParamsToolResources
780 return param.MarshalObject(r, (*shadow)(&r))
754 return param.MarshalObject(r, (*shadow)(&r))
781}
755}
756+func (r *BetaThreadNewParamsToolResources) UnmarshalJSON(data []byte) error {
757+ return apijson.UnmarshalRoot(data, r)
758+}
782
759
783type BetaThreadNewParamsToolResourcesCodeInterpreter struct {
760type BetaThreadNewParamsToolResourcesCodeInterpreter struct {
784 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
761 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
@@ -788,15 +765,13 @@ type BetaThreadNewParamsToolResourcesCodeInterpreter struct {
788 paramObj
765 paramObj
789}
766}
790
767
791−// IsPresent returns true if the field's value is not omitted and not the JSON
792−// "null". To check if this field is omitted, use [param.IsOmitted].
793−func (f BetaThreadNewParamsToolResourcesCodeInterpreter) IsPresent() bool {
794− return !param.IsOmitted(f) && !f.IsNull()
795−}
796func (r BetaThreadNewParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
768func (r BetaThreadNewParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
797 type shadow BetaThreadNewParamsToolResourcesCodeInterpreter
769 type shadow BetaThreadNewParamsToolResourcesCodeInterpreter
798 return param.MarshalObject(r, (*shadow)(&r))
770 return param.MarshalObject(r, (*shadow)(&r))
799}
771}
772+func (r *BetaThreadNewParamsToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error {
773+ return apijson.UnmarshalRoot(data, r)
774+}
800
775
801type BetaThreadNewParamsToolResourcesFileSearch struct {
776type BetaThreadNewParamsToolResourcesFileSearch struct {
802 // The
777 // The
@@ -812,15 +787,13 @@ type BetaThreadNewParamsToolResourcesFileSearch struct {
812 paramObj
787 paramObj
813}
788}
814
789
815−// IsPresent returns true if the field's value is not omitted and not the JSON
816−// "null". To check if this field is omitted, use [param.IsOmitted].
817−func (f BetaThreadNewParamsToolResourcesFileSearch) IsPresent() bool {
818− return !param.IsOmitted(f) && !f.IsNull()
819−}
820func (r BetaThreadNewParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
790func (r BetaThreadNewParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
821 type shadow BetaThreadNewParamsToolResourcesFileSearch
791 type shadow BetaThreadNewParamsToolResourcesFileSearch
822 return param.MarshalObject(r, (*shadow)(&r))
792 return param.MarshalObject(r, (*shadow)(&r))
823}
793}
794+func (r *BetaThreadNewParamsToolResourcesFileSearch) UnmarshalJSON(data []byte) error {
795+ return apijson.UnmarshalRoot(data, r)
796+}
824
797
825type BetaThreadNewParamsToolResourcesFileSearchVectorStore struct {
798type BetaThreadNewParamsToolResourcesFileSearchVectorStore struct {
826 // Set of 16 key-value pairs that can be attached to an object. This can be useful
799 // Set of 16 key-value pairs that can be attached to an object. This can be useful
@@ -829,7 +802,7 @@ type BetaThreadNewParamsToolResourcesFileSearchVectorStore struct {
829 //
802 //
830 // Keys are strings with a maximum length of 64 characters. Values are strings with
803 // Keys are strings with a maximum length of 64 characters. Values are strings with
831 // a maximum length of 512 characters.
804 // a maximum length of 512 characters.
832− Metadata shared.MetadataParam `json:"metadata,omitzero"`
805+ Metadata shared.Metadata `json:"metadata,omitzero"`
833 // The chunking strategy used to chunk the file(s). If not set, will use the `auto`
806 // The chunking strategy used to chunk the file(s). If not set, will use the `auto`
834 // strategy.
807 // strategy.
835 ChunkingStrategy BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
808 ChunkingStrategy BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
@@ -840,15 +813,13 @@ type BetaThreadNewParamsToolResourcesFileSearchVectorStore struct {
840 paramObj
813 paramObj
841}
814}
842
815
843−// IsPresent returns true if the field's value is not omitted and not the JSON
844−// "null". To check if this field is omitted, use [param.IsOmitted].
845−func (f BetaThreadNewParamsToolResourcesFileSearchVectorStore) IsPresent() bool {
846− return !param.IsOmitted(f) && !f.IsNull()
847−}
848func (r BetaThreadNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) {
816func (r BetaThreadNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) {
849 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStore
817 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStore
850 return param.MarshalObject(r, (*shadow)(&r))
818 return param.MarshalObject(r, (*shadow)(&r))
851}
819}
820+func (r *BetaThreadNewParamsToolResourcesFileSearchVectorStore) UnmarshalJSON(data []byte) error {
821+ return apijson.UnmarshalRoot(data, r)
822+}
852
823
853// Only one field can be non-zero.
824// Only one field can be non-zero.
854//
825//
@@ -859,13 +830,11 @@ type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion
859 paramUnion
830 paramUnion
860}
831}
861
832
862−// IsPresent returns true if the field's value is not omitted and not the JSON
863−// "null". To check if this field is omitted, use [param.IsOmitted].
864−func (u BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) IsPresent() bool {
865− return !param.IsOmitted(u) && !u.IsNull()
866−}
867func (u BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
833func (u BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
834+ return param.MarshalUnion(u, u.OfAuto, u.OfStatic)
835+}
868− return param.MarshalUnion[BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion](u.OfAuto, u.OfStatic)
836+func (u *BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) UnmarshalJSON(data []byte) error {
837+ return apijson.UnmarshalRoot(data, u)
869}
838}
870
839
871func (u *BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) asAny() any {
840func (u *BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion) asAny() any {
@@ -898,40 +867,35 @@ func (u BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUni
898func init() {
867func init() {
899 apijson.RegisterUnion[BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion](
868 apijson.RegisterUnion[BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyUnion](
900 "type",
869 "type",
901− apijson.UnionVariant{
902− TypeFilter: gjson.JSON,
903− Type: reflect.TypeOf(BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto{}),
870+ apijson.Discriminator[BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto]("auto"),
904− DiscriminatorValue: "auto",
905− },
906− apijson.UnionVariant{
907− TypeFilter: gjson.JSON,
908− Type: reflect.TypeOf(BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic{}),
871+ apijson.Discriminator[BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic]("static"),
909− DiscriminatorValue: "static",
910− },
911 )
872 )
912}
873}
913
874
875+func NewBetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto() BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto {
876+ return BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto{
877+ Type: "auto",
878+ }
879+}
880+
914// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of
881// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of
915// `800` and `chunk_overlap_tokens` of `400`.
882// `800` and `chunk_overlap_tokens` of `400`.
916//
883//
917−// The property Type is required.
884+// This struct has a constant value, construct it with
885+// [NewBetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto].
918type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto struct {
886type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto struct {
919 // Always `auto`.
887 // Always `auto`.
920− //
921− // This field can be elided, and will marshal its zero value as "auto".
922 Type constant.Auto `json:"type,required"`
888 Type constant.Auto `json:"type,required"`
923 paramObj
889 paramObj
924}
890}
925
891
926−// IsPresent returns true if the field's value is not omitted and not the JSON
927−// "null". To check if this field is omitted, use [param.IsOmitted].
928−func (f BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) IsPresent() bool {
929− return !param.IsOmitted(f) && !f.IsNull()
930−}
931func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) MarshalJSON() (data []byte, err error) {
892func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) MarshalJSON() (data []byte, err error) {
932 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto
893 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto
933 return param.MarshalObject(r, (*shadow)(&r))
894 return param.MarshalObject(r, (*shadow)(&r))
934}
895}
896+func (r *BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyAuto) UnmarshalJSON(data []byte) error {
897+ return apijson.UnmarshalRoot(data, r)
898+}
935
899
936// The properties Static, Type are required.
900// The properties Static, Type are required.
937type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic struct {
901type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic struct {
@@ -943,15 +907,13 @@ type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic
943 paramObj
907 paramObj
944}
908}
945
909
946−// IsPresent returns true if the field's value is not omitted and not the JSON
947−// "null". To check if this field is omitted, use [param.IsOmitted].
948−func (f BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) IsPresent() bool {
949− return !param.IsOmitted(f) && !f.IsNull()
950−}
951func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) MarshalJSON() (data []byte, err error) {
910func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) MarshalJSON() (data []byte, err error) {
952 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic
911 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic
953 return param.MarshalObject(r, (*shadow)(&r))
912 return param.MarshalObject(r, (*shadow)(&r))
954}
913}
914+func (r *BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic) UnmarshalJSON(data []byte) error {
915+ return apijson.UnmarshalRoot(data, r)
916+}
955
917
956// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required.
918// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required.
957type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic struct {
919type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic struct {
@@ -965,15 +927,13 @@ type BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStatic
965 paramObj
927 paramObj
966}
928}
967
929
968−// IsPresent returns true if the field's value is not omitted and not the JSON
969−// "null". To check if this field is omitted, use [param.IsOmitted].
970−func (f BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) IsPresent() bool {
971− return !param.IsOmitted(f) && !f.IsNull()
972−}
973func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) {
930func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) {
974 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic
931 type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic
975 return param.MarshalObject(r, (*shadow)(&r))
932 return param.MarshalObject(r, (*shadow)(&r))
976}
933}
934+func (r *BetaThreadNewParamsToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) UnmarshalJSON(data []byte) error {
935+ return apijson.UnmarshalRoot(data, r)
936+}
977
937
978type BetaThreadUpdateParams struct {
938type BetaThreadUpdateParams struct {
979 // Set of 16 key-value pairs that can be attached to an object. This can be useful
939 // Set of 16 key-value pairs that can be attached to an object. This can be useful
@@ -982,7 +942,7 @@ type BetaThreadUpdateParams struct {
982 //
942 //
983 // Keys are strings with a maximum length of 64 characters. Values are strings with
943 // Keys are strings with a maximum length of 64 characters. Values are strings with
984 // a maximum length of 512 characters.
944 // a maximum length of 512 characters.
985− Metadata shared.MetadataParam `json:"metadata,omitzero"`
945+ Metadata shared.Metadata `json:"metadata,omitzero"`
986 // A set of resources that are made available to the assistant's tools in this
946 // A set of resources that are made available to the assistant's tools in this
987 // thread. The resources are specific to the type of tool. For example, the
947 // thread. The resources are specific to the type of tool. For example, the
988 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
948 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
@@ -991,14 +951,13 @@ type BetaThreadUpdateParams struct {
991 paramObj
951 paramObj
992}
952}
993
953
994−// IsPresent returns true if the field's value is not omitted and not the JSON
995−// "null". To check if this field is omitted, use [param.IsOmitted].
996−func (f BetaThreadUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
997−
998func (r BetaThreadUpdateParams) MarshalJSON() (data []byte, err error) {
954func (r BetaThreadUpdateParams) MarshalJSON() (data []byte, err error) {
999 type shadow BetaThreadUpdateParams
955 type shadow BetaThreadUpdateParams
1000 return param.MarshalObject(r, (*shadow)(&r))
956 return param.MarshalObject(r, (*shadow)(&r))
1001}
957}
958+func (r *BetaThreadUpdateParams) UnmarshalJSON(data []byte) error {
959+ return apijson.UnmarshalRoot(data, r)
960+}
1002
961
1003// A set of resources that are made available to the assistant's tools in this
962// A set of resources that are made available to the assistant's tools in this
1004// thread. The resources are specific to the type of tool. For example, the
963// thread. The resources are specific to the type of tool. For example, the
@@ -1010,15 +969,13 @@ type BetaThreadUpdateParamsToolResources struct {
1010 paramObj
969 paramObj
1011}
970}
1012
971
1013−// IsPresent returns true if the field's value is not omitted and not the JSON
1014−// "null". To check if this field is omitted, use [param.IsOmitted].
1015−func (f BetaThreadUpdateParamsToolResources) IsPresent() bool {
1016− return !param.IsOmitted(f) && !f.IsNull()
1017−}
1018func (r BetaThreadUpdateParamsToolResources) MarshalJSON() (data []byte, err error) {
972func (r BetaThreadUpdateParamsToolResources) MarshalJSON() (data []byte, err error) {
1019 type shadow BetaThreadUpdateParamsToolResources
973 type shadow BetaThreadUpdateParamsToolResources
1020 return param.MarshalObject(r, (*shadow)(&r))
974 return param.MarshalObject(r, (*shadow)(&r))
1021}
975}
976+func (r *BetaThreadUpdateParamsToolResources) UnmarshalJSON(data []byte) error {
977+ return apijson.UnmarshalRoot(data, r)
978+}
1022
979
1023type BetaThreadUpdateParamsToolResourcesCodeInterpreter struct {
980type BetaThreadUpdateParamsToolResourcesCodeInterpreter struct {
1024 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
981 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
@@ -1028,15 +985,13 @@ type BetaThreadUpdateParamsToolResourcesCodeInterpreter struct {
1028 paramObj
985 paramObj
1029}
986}
1030
987
1031−// IsPresent returns true if the field's value is not omitted and not the JSON
1032−// "null". To check if this field is omitted, use [param.IsOmitted].
1033−func (f BetaThreadUpdateParamsToolResourcesCodeInterpreter) IsPresent() bool {
1034− return !param.IsOmitted(f) && !f.IsNull()
1035−}
1036func (r BetaThreadUpdateParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
988func (r BetaThreadUpdateParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1037 type shadow BetaThreadUpdateParamsToolResourcesCodeInterpreter
989 type shadow BetaThreadUpdateParamsToolResourcesCodeInterpreter
1038 return param.MarshalObject(r, (*shadow)(&r))
990 return param.MarshalObject(r, (*shadow)(&r))
1039}
991}
992+func (r *BetaThreadUpdateParamsToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error {
993+ return apijson.UnmarshalRoot(data, r)
994+}
1040
995
1041type BetaThreadUpdateParamsToolResourcesFileSearch struct {
996type BetaThreadUpdateParamsToolResourcesFileSearch struct {
1042 // The
997 // The
@@ -1047,15 +1002,13 @@ type BetaThreadUpdateParamsToolResourcesFileSearch struct {
1047 paramObj
1002 paramObj
1048}
1003}
1049
1004
1050−// IsPresent returns true if the field's value is not omitted and not the JSON
1051−// "null". To check if this field is omitted, use [param.IsOmitted].
1052−func (f BetaThreadUpdateParamsToolResourcesFileSearch) IsPresent() bool {
1053− return !param.IsOmitted(f) && !f.IsNull()
1054−}
1055func (r BetaThreadUpdateParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1005func (r BetaThreadUpdateParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1056 type shadow BetaThreadUpdateParamsToolResourcesFileSearch
1006 type shadow BetaThreadUpdateParamsToolResourcesFileSearch
1057 return param.MarshalObject(r, (*shadow)(&r))
1007 return param.MarshalObject(r, (*shadow)(&r))
1058}
1008}
1009+func (r *BetaThreadUpdateParamsToolResourcesFileSearch) UnmarshalJSON(data []byte) error {
1010+ return apijson.UnmarshalRoot(data, r)
1011+}
1059
1012
1060type BetaThreadNewAndRunParams struct {
1013type BetaThreadNewAndRunParams struct {
1061 // The ID of the
1014 // The ID of the
@@ -1097,7 +1050,7 @@ type BetaThreadNewAndRunParams struct {
1097 //
1050 //
1098 // Keys are strings with a maximum length of 64 characters. Values are strings with
1051 // Keys are strings with a maximum length of 64 characters. Values are strings with
1099 // a maximum length of 512 characters.
1052 // a maximum length of 512 characters.
1100− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1053+ Metadata shared.Metadata `json:"metadata,omitzero"`
1101 // The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to
1054 // The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to
1102 // be used to execute this run. If a value is provided here, it will override the
1055 // be used to execute this run. If a value is provided here, it will override the
1103 // model associated with the assistant. If not, the model associated with the
1056 // model associated with the assistant. If not, the model associated with the
@@ -1110,7 +1063,7 @@ type BetaThreadNewAndRunParams struct {
1110 ToolResources BetaThreadNewAndRunParamsToolResources `json:"tool_resources,omitzero"`
1063 ToolResources BetaThreadNewAndRunParamsToolResources `json:"tool_resources,omitzero"`
1111 // Override the tools the assistant can use for this run. This is useful for
1064 // Override the tools the assistant can use for this run. This is useful for
1112 // modifying the behavior on a per-run basis.
1065 // modifying the behavior on a per-run basis.
1113− Tools []BetaThreadNewAndRunParamsToolUnion `json:"tools,omitzero"`
1066+ Tools []AssistantToolUnionParam `json:"tools,omitzero"`
1114 // Controls for how a thread will be truncated prior to the run. Use this to
1067 // Controls for how a thread will be truncated prior to the run. Use this to
1115 // control the intial context window of the run.
1068 // control the intial context window of the run.
1116 TruncationStrategy BetaThreadNewAndRunParamsTruncationStrategy `json:"truncation_strategy,omitzero"`
1069 TruncationStrategy BetaThreadNewAndRunParamsTruncationStrategy `json:"truncation_strategy,omitzero"`
@@ -1149,14 +1102,13 @@ type BetaThreadNewAndRunParams struct {
1149 paramObj
1102 paramObj
1150}
1103}
1151
1104
1152−// IsPresent returns true if the field's value is not omitted and not the JSON
1153−// "null". To check if this field is omitted, use [param.IsOmitted].
1154−func (f BetaThreadNewAndRunParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1155−
1156func (r BetaThreadNewAndRunParams) MarshalJSON() (data []byte, err error) {
1105func (r BetaThreadNewAndRunParams) MarshalJSON() (data []byte, err error) {
1157 type shadow BetaThreadNewAndRunParams
1106 type shadow BetaThreadNewAndRunParams
1158 return param.MarshalObject(r, (*shadow)(&r))
1107 return param.MarshalObject(r, (*shadow)(&r))
1159}
1108}
1109+func (r *BetaThreadNewAndRunParams) UnmarshalJSON(data []byte) error {
1110+ return apijson.UnmarshalRoot(data, r)
1111+}
1160
1112
1161// Options to create a new thread. If no thread is provided when running a request,
1113// Options to create a new thread. If no thread is provided when running a request,
1162// an empty thread will be created.
1114// an empty thread will be created.
@@ -1167,7 +1119,7 @@ type BetaThreadNewAndRunParamsThread struct {
1167 //
1119 //
1168 // Keys are strings with a maximum length of 64 characters. Values are strings with
1120 // Keys are strings with a maximum length of 64 characters. Values are strings with
1169 // a maximum length of 512 characters.
1121 // a maximum length of 512 characters.
1170− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1122+ Metadata shared.Metadata `json:"metadata,omitzero"`
1171 // A set of resources that are made available to the assistant's tools in this
1123 // A set of resources that are made available to the assistant's tools in this
1172 // thread. The resources are specific to the type of tool. For example, the
1124 // thread. The resources are specific to the type of tool. For example, the
1173 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
1125 // `code_interpreter` tool requires a list of file IDs, while the `file_search`
@@ -1179,13 +1131,13 @@ type BetaThreadNewAndRunParamsThread struct {
1179 paramObj
1131 paramObj
1180}
1132}
1181
1133
1182−// IsPresent returns true if the field's value is not omitted and not the JSON
1183−// "null". To check if this field is omitted, use [param.IsOmitted].
1184−func (f BetaThreadNewAndRunParamsThread) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1185func (r BetaThreadNewAndRunParamsThread) MarshalJSON() (data []byte, err error) {
1134func (r BetaThreadNewAndRunParamsThread) MarshalJSON() (data []byte, err error) {
1186 type shadow BetaThreadNewAndRunParamsThread
1135 type shadow BetaThreadNewAndRunParamsThread
1187 return param.MarshalObject(r, (*shadow)(&r))
1136 return param.MarshalObject(r, (*shadow)(&r))
1188}
1137}
1138+func (r *BetaThreadNewAndRunParamsThread) UnmarshalJSON(data []byte) error {
1139+ return apijson.UnmarshalRoot(data, r)
1140+}
1189
1141
1190// The properties Content, Role are required.
1142// The properties Content, Role are required.
1191type BetaThreadNewAndRunParamsThreadMessage struct {
1143type BetaThreadNewAndRunParamsThreadMessage struct {
@@ -1208,23 +1160,21 @@ type BetaThreadNewAndRunParamsThreadMessage struct {
1208 //
1160 //
1209 // Keys are strings with a maximum length of 64 characters. Values are strings with
1161 // Keys are strings with a maximum length of 64 characters. Values are strings with
1210 // a maximum length of 512 characters.
1162 // a maximum length of 512 characters.
1211− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1163+ Metadata shared.Metadata `json:"metadata,omitzero"`
1212 paramObj
1164 paramObj
1213}
1165}
1214
1166
1215−// IsPresent returns true if the field's value is not omitted and not the JSON
1216−// "null". To check if this field is omitted, use [param.IsOmitted].
1217−func (f BetaThreadNewAndRunParamsThreadMessage) IsPresent() bool {
1218− return !param.IsOmitted(f) && !f.IsNull()
1219−}
1220func (r BetaThreadNewAndRunParamsThreadMessage) MarshalJSON() (data []byte, err error) {
1167func (r BetaThreadNewAndRunParamsThreadMessage) MarshalJSON() (data []byte, err error) {
1221 type shadow BetaThreadNewAndRunParamsThreadMessage
1168 type shadow BetaThreadNewAndRunParamsThreadMessage
1222 return param.MarshalObject(r, (*shadow)(&r))
1169 return param.MarshalObject(r, (*shadow)(&r))
1223}
1170}
1171+func (r *BetaThreadNewAndRunParamsThreadMessage) UnmarshalJSON(data []byte) error {
1172+ return apijson.UnmarshalRoot(data, r)
1173+}
1224
1174
1225func init() {
1175func init() {
1226 apijson.RegisterFieldValidator[BetaThreadNewAndRunParamsThreadMessage](
1176 apijson.RegisterFieldValidator[BetaThreadNewAndRunParamsThreadMessage](
1227− "Role", false, "user", "assistant",
1177+ "role", "user", "assistant",
1228 )
1178 )
1229}
1179}
1230
1180
@@ -1237,13 +1187,11 @@ type BetaThreadNewAndRunParamsThreadMessageContentUnion struct {
1237 paramUnion
1187 paramUnion
1238}
1188}
1239
1189
1240−// IsPresent returns true if the field's value is not omitted and not the JSON
1241−// "null". To check if this field is omitted, use [param.IsOmitted].
1242−func (u BetaThreadNewAndRunParamsThreadMessageContentUnion) IsPresent() bool {
1243− return !param.IsOmitted(u) && !u.IsNull()
1244−}
1245func (u BetaThreadNewAndRunParamsThreadMessageContentUnion) MarshalJSON() ([]byte, error) {
1190func (u BetaThreadNewAndRunParamsThreadMessageContentUnion) MarshalJSON() ([]byte, error) {
1191+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
1192+}
1246− return param.MarshalUnion[BetaThreadNewAndRunParamsThreadMessageContentUnion](u.OfString, u.OfArrayOfContentParts)
1193+func (u *BetaThreadNewAndRunParamsThreadMessageContentUnion) UnmarshalJSON(data []byte) error {
1194+ return apijson.UnmarshalRoot(data, u)
1247}
1195}
1248
1196
1249func (u *BetaThreadNewAndRunParamsThreadMessageContentUnion) asAny() any {
1197func (u *BetaThreadNewAndRunParamsThreadMessageContentUnion) asAny() any {
@@ -1263,15 +1211,13 @@ type BetaThreadNewAndRunParamsThreadMessageAttachment struct {
1263 paramObj
1211 paramObj
1264}
1212}
1265
1213
1266−// IsPresent returns true if the field's value is not omitted and not the JSON
1267−// "null". To check if this field is omitted, use [param.IsOmitted].
1268−func (f BetaThreadNewAndRunParamsThreadMessageAttachment) IsPresent() bool {
1269− return !param.IsOmitted(f) && !f.IsNull()
1270−}
1271func (r BetaThreadNewAndRunParamsThreadMessageAttachment) MarshalJSON() (data []byte, err error) {
1214func (r BetaThreadNewAndRunParamsThreadMessageAttachment) MarshalJSON() (data []byte, err error) {
1272 type shadow BetaThreadNewAndRunParamsThreadMessageAttachment
1215 type shadow BetaThreadNewAndRunParamsThreadMessageAttachment
1273 return param.MarshalObject(r, (*shadow)(&r))
1216 return param.MarshalObject(r, (*shadow)(&r))
1274}
1217}
1218+func (r *BetaThreadNewAndRunParamsThreadMessageAttachment) UnmarshalJSON(data []byte) error {
1219+ return apijson.UnmarshalRoot(data, r)
1220+}
1275
1221
1276// Only one field can be non-zero.
1222// Only one field can be non-zero.
1277//
1223//
@@ -1282,13 +1228,11 @@ type BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion struct {
1282 paramUnion
1228 paramUnion
1283}
1229}
1284
1230
1285−// IsPresent returns true if the field's value is not omitted and not the JSON
1286−// "null". To check if this field is omitted, use [param.IsOmitted].
1287−func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) IsPresent() bool {
1288− return !param.IsOmitted(u) && !u.IsNull()
1289−}
1290func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) {
1231func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) {
1232+ return param.MarshalUnion(u, u.OfCodeInterpreter, u.OfFileSearch)
1233+}
1291− return param.MarshalUnion[BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch)
1234+func (u *BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) UnmarshalJSON(data []byte) error {
1235+ return apijson.UnmarshalRoot(data, u)
1292}
1236}
1293
1237
1294func (u *BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) asAny() any {
1238func (u *BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) asAny() any {
@@ -1313,37 +1257,32 @@ func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) GetType() *st
1313func init() {
1257func init() {
1314 apijson.RegisterUnion[BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion](
1258 apijson.RegisterUnion[BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion](
1315 "type",
1259 "type",
1316− apijson.UnionVariant{
1317− TypeFilter: gjson.JSON,
1318− Type: reflect.TypeOf(CodeInterpreterToolParam{}),
1260+ apijson.Discriminator[CodeInterpreterToolParam]("code_interpreter"),
1319− DiscriminatorValue: "code_interpreter",
1320− },
1321− apijson.UnionVariant{
1322− TypeFilter: gjson.JSON,
1323− Type: reflect.TypeOf(BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch{}),
1261+ apijson.Discriminator[BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch]("file_search"),
1324− DiscriminatorValue: "file_search",
1325− },
1326 )
1262 )
1327}
1263}
1328
1264
1329−// The property Type is required.
1265+func NewBetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch() BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch {
1266+ return BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch{
1267+ Type: "file_search",
1268+ }
1269+}
1270+
1271+// This struct has a constant value, construct it with
1272+// [NewBetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch].
1330type BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch struct {
1273type BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch struct {
1331 // The type of tool being defined: `file_search`
1274 // The type of tool being defined: `file_search`
1332− //
1333− // This field can be elided, and will marshal its zero value as "file_search".
1334 Type constant.FileSearch `json:"type,required"`
1275 Type constant.FileSearch `json:"type,required"`
1335 paramObj
1276 paramObj
1336}
1277}
1337
1278
1338−// IsPresent returns true if the field's value is not omitted and not the JSON
1339−// "null". To check if this field is omitted, use [param.IsOmitted].
1340−func (f BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch) IsPresent() bool {
1341− return !param.IsOmitted(f) && !f.IsNull()
1342−}
1343func (r BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
1279func (r BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
1344 type shadow BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch
1280 type shadow BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch
1345 return param.MarshalObject(r, (*shadow)(&r))
1281 return param.MarshalObject(r, (*shadow)(&r))
1346}
1282}
1283+func (r *BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch) UnmarshalJSON(data []byte) error {
1284+ return apijson.UnmarshalRoot(data, r)
1285+}
1347
1286
1348// A set of resources that are made available to the assistant's tools in this
1287// A set of resources that are made available to the assistant's tools in this
1349// thread. The resources are specific to the type of tool. For example, the
1288// thread. The resources are specific to the type of tool. For example, the
@@ -1355,15 +1294,13 @@ type BetaThreadNewAndRunParamsThreadToolResources struct {
1355 paramObj
1294 paramObj
1356}
1295}
1357
1296
1358−// IsPresent returns true if the field's value is not omitted and not the JSON
1359−// "null". To check if this field is omitted, use [param.IsOmitted].
1360−func (f BetaThreadNewAndRunParamsThreadToolResources) IsPresent() bool {
1361− return !param.IsOmitted(f) && !f.IsNull()
1362−}
1363func (r BetaThreadNewAndRunParamsThreadToolResources) MarshalJSON() (data []byte, err error) {
1297func (r BetaThreadNewAndRunParamsThreadToolResources) MarshalJSON() (data []byte, err error) {
1364 type shadow BetaThreadNewAndRunParamsThreadToolResources
1298 type shadow BetaThreadNewAndRunParamsThreadToolResources
1365 return param.MarshalObject(r, (*shadow)(&r))
1299 return param.MarshalObject(r, (*shadow)(&r))
1366}
1300}
1301+func (r *BetaThreadNewAndRunParamsThreadToolResources) UnmarshalJSON(data []byte) error {
1302+ return apijson.UnmarshalRoot(data, r)
1303+}
1367
1304
1368type BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter struct {
1305type BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter struct {
1369 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
1306 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
@@ -1373,15 +1310,13 @@ type BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter struct {
1373 paramObj
1310 paramObj
1374}
1311}
1375
1312
1376−// IsPresent returns true if the field's value is not omitted and not the JSON
1377−// "null". To check if this field is omitted, use [param.IsOmitted].
1378−func (f BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter) IsPresent() bool {
1379− return !param.IsOmitted(f) && !f.IsNull()
1380−}
1381func (r BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1313func (r BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1382 type shadow BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter
1314 type shadow BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter
1383 return param.MarshalObject(r, (*shadow)(&r))
1315 return param.MarshalObject(r, (*shadow)(&r))
1384}
1316}
1317+func (r *BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error {
1318+ return apijson.UnmarshalRoot(data, r)
1319+}
1385
1320
1386type BetaThreadNewAndRunParamsThreadToolResourcesFileSearch struct {
1321type BetaThreadNewAndRunParamsThreadToolResourcesFileSearch struct {
1387 // The
1322 // The
@@ -1397,15 +1332,13 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearch struct {
1397 paramObj
1332 paramObj
1398}
1333}
1399
1334
1400−// IsPresent returns true if the field's value is not omitted and not the JSON
1401−// "null". To check if this field is omitted, use [param.IsOmitted].
1402−func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearch) IsPresent() bool {
1403− return !param.IsOmitted(f) && !f.IsNull()
1404−}
1405func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1335func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1406 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearch
1336 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearch
1407 return param.MarshalObject(r, (*shadow)(&r))
1337 return param.MarshalObject(r, (*shadow)(&r))
1408}
1338}
1339+func (r *BetaThreadNewAndRunParamsThreadToolResourcesFileSearch) UnmarshalJSON(data []byte) error {
1340+ return apijson.UnmarshalRoot(data, r)
1341+}
1409
1342
1410type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore struct {
1343type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore struct {
1411 // Set of 16 key-value pairs that can be attached to an object. This can be useful
1344 // Set of 16 key-value pairs that can be attached to an object. This can be useful
@@ -1414,7 +1347,7 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore struct {
1414 //
1347 //
1415 // Keys are strings with a maximum length of 64 characters. Values are strings with
1348 // Keys are strings with a maximum length of 64 characters. Values are strings with
1416 // a maximum length of 512 characters.
1349 // a maximum length of 512 characters.
1417− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1350+ Metadata shared.Metadata `json:"metadata,omitzero"`
1418 // The chunking strategy used to chunk the file(s). If not set, will use the `auto`
1351 // The chunking strategy used to chunk the file(s). If not set, will use the `auto`
1419 // strategy.
1352 // strategy.
1420 ChunkingStrategy BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
1353 ChunkingStrategy BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion `json:"chunking_strategy,omitzero"`
@@ -1425,15 +1358,13 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore struct {
1425 paramObj
1358 paramObj
1426}
1359}
1427
1360
1428−// IsPresent returns true if the field's value is not omitted and not the JSON
1429−// "null". To check if this field is omitted, use [param.IsOmitted].
1430−func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) IsPresent() bool {
1431− return !param.IsOmitted(f) && !f.IsNull()
1432−}
1433func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) {
1361func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) {
1434 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore
1362 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore
1435 return param.MarshalObject(r, (*shadow)(&r))
1363 return param.MarshalObject(r, (*shadow)(&r))
1436}
1364}
1365+func (r *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) UnmarshalJSON(data []byte) error {
1366+ return apijson.UnmarshalRoot(data, r)
1367+}
1437
1368
1438// Only one field can be non-zero.
1369// Only one field can be non-zero.
1439//
1370//
@@ -1444,13 +1375,11 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingSt
1444 paramUnion
1375 paramUnion
1445}
1376}
1446
1377
1447−// IsPresent returns true if the field's value is not omitted and not the JSON
1448−// "null". To check if this field is omitted, use [param.IsOmitted].
1449−func (u BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion) IsPresent() bool {
1450− return !param.IsOmitted(u) && !u.IsNull()
1451−}
1452func (u BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
1378func (u BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion) MarshalJSON() ([]byte, error) {
1379+ return param.MarshalUnion(u, u.OfAuto, u.OfStatic)
1380+}
1453− return param.MarshalUnion[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion](u.OfAuto, u.OfStatic)
1381+func (u *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion) UnmarshalJSON(data []byte) error {
1382+ return apijson.UnmarshalRoot(data, u)
1454}
1383}
1455
1384
1456func (u *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion) asAny() any {
1385func (u *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion) asAny() any {
@@ -1483,40 +1412,35 @@ func (u BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkin
1483func init() {
1412func init() {
1484 apijson.RegisterUnion[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion](
1413 apijson.RegisterUnion[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyUnion](
1485 "type",
1414 "type",
1486− apijson.UnionVariant{
1487− TypeFilter: gjson.JSON,
1488− Type: reflect.TypeOf(BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto{}),
1415+ apijson.Discriminator[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto]("auto"),
1489− DiscriminatorValue: "auto",
1490− },
1491− apijson.UnionVariant{
1492− TypeFilter: gjson.JSON,
1493− Type: reflect.TypeOf(BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic{}),
1416+ apijson.Discriminator[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic]("static"),
1494− DiscriminatorValue: "static",
1495− },
1496 )
1417 )
1497}
1418}
1498
1419
1420+func NewBetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto() BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto {
1421+ return BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto{
1422+ Type: "auto",
1423+ }
1424+}
1425+
1499// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of
1426// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of
1500// `800` and `chunk_overlap_tokens` of `400`.
1427// `800` and `chunk_overlap_tokens` of `400`.
1501//
1428//
1502−// The property Type is required.
1429+// This struct has a constant value, construct it with
1430+// [NewBetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto].
1503type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto struct {
1431type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto struct {
1504 // Always `auto`.
1432 // Always `auto`.
1505− //
1506− // This field can be elided, and will marshal its zero value as "auto".
1507 Type constant.Auto `json:"type,required"`
1433 Type constant.Auto `json:"type,required"`
1508 paramObj
1434 paramObj
1509}
1435}
1510
1436
1511−// IsPresent returns true if the field's value is not omitted and not the JSON
1512−// "null". To check if this field is omitted, use [param.IsOmitted].
1513−func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto) IsPresent() bool {
1514− return !param.IsOmitted(f) && !f.IsNull()
1515−}
1516func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto) MarshalJSON() (data []byte, err error) {
1437func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto) MarshalJSON() (data []byte, err error) {
1517 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto
1438 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto
1518 return param.MarshalObject(r, (*shadow)(&r))
1439 return param.MarshalObject(r, (*shadow)(&r))
1519}
1440}
1441+func (r *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyAuto) UnmarshalJSON(data []byte) error {
1442+ return apijson.UnmarshalRoot(data, r)
1443+}
1520
1444
1521// The properties Static, Type are required.
1445// The properties Static, Type are required.
1522type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic struct {
1446type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic struct {
@@ -1528,15 +1452,13 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingSt
1528 paramObj
1452 paramObj
1529}
1453}
1530
1454
1531−// IsPresent returns true if the field's value is not omitted and not the JSON
1532−// "null". To check if this field is omitted, use [param.IsOmitted].
1533−func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic) IsPresent() bool {
1534− return !param.IsOmitted(f) && !f.IsNull()
1535−}
1536func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic) MarshalJSON() (data []byte, err error) {
1455func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic) MarshalJSON() (data []byte, err error) {
1537 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic
1456 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic
1538 return param.MarshalObject(r, (*shadow)(&r))
1457 return param.MarshalObject(r, (*shadow)(&r))
1539}
1458}
1459+func (r *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStatic) UnmarshalJSON(data []byte) error {
1460+ return apijson.UnmarshalRoot(data, r)
1461+}
1540
1462
1541// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required.
1463// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required.
1542type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic struct {
1464type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic struct {
@@ -1550,15 +1472,13 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingSt
1550 paramObj
1472 paramObj
1551}
1473}
1552
1474
1553−// IsPresent returns true if the field's value is not omitted and not the JSON
1554−// "null". To check if this field is omitted, use [param.IsOmitted].
1555−func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) IsPresent() bool {
1556− return !param.IsOmitted(f) && !f.IsNull()
1557−}
1558func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) {
1475func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) {
1559 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic
1476 type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic
1560 return param.MarshalObject(r, (*shadow)(&r))
1477 return param.MarshalObject(r, (*shadow)(&r))
1561}
1478}
1479+func (r *BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoreChunkingStrategyStaticStatic) UnmarshalJSON(data []byte) error {
1480+ return apijson.UnmarshalRoot(data, r)
1481+}
1562
1482
1563// A set of resources that are used by the assistant's tools. The resources are
1483// A set of resources that are used by the assistant's tools. The resources are
1564// specific to the type of tool. For example, the `code_interpreter` tool requires
1484// specific to the type of tool. For example, the `code_interpreter` tool requires
@@ -1570,15 +1490,13 @@ type BetaThreadNewAndRunParamsToolResources struct {
1570 paramObj
1490 paramObj
1571}
1491}
1572
1492
1573−// IsPresent returns true if the field's value is not omitted and not the JSON
1574−// "null". To check if this field is omitted, use [param.IsOmitted].
1575−func (f BetaThreadNewAndRunParamsToolResources) IsPresent() bool {
1576− return !param.IsOmitted(f) && !f.IsNull()
1577−}
1578func (r BetaThreadNewAndRunParamsToolResources) MarshalJSON() (data []byte, err error) {
1493func (r BetaThreadNewAndRunParamsToolResources) MarshalJSON() (data []byte, err error) {
1579 type shadow BetaThreadNewAndRunParamsToolResources
1494 type shadow BetaThreadNewAndRunParamsToolResources
1580 return param.MarshalObject(r, (*shadow)(&r))
1495 return param.MarshalObject(r, (*shadow)(&r))
1581}
1496}
1497+func (r *BetaThreadNewAndRunParamsToolResources) UnmarshalJSON(data []byte) error {
1498+ return apijson.UnmarshalRoot(data, r)
1499+}
1582
1500
1583type BetaThreadNewAndRunParamsToolResourcesCodeInterpreter struct {
1501type BetaThreadNewAndRunParamsToolResourcesCodeInterpreter struct {
1584 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
1502 // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made
@@ -1588,15 +1506,13 @@ type BetaThreadNewAndRunParamsToolResourcesCodeInterpreter struct {
1588 paramObj
1506 paramObj
1589}
1507}
1590
1508
1591−// IsPresent returns true if the field's value is not omitted and not the JSON
1592−// "null". To check if this field is omitted, use [param.IsOmitted].
1593−func (f BetaThreadNewAndRunParamsToolResourcesCodeInterpreter) IsPresent() bool {
1594− return !param.IsOmitted(f) && !f.IsNull()
1595−}
1596func (r BetaThreadNewAndRunParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1509func (r BetaThreadNewAndRunParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) {
1597 type shadow BetaThreadNewAndRunParamsToolResourcesCodeInterpreter
1510 type shadow BetaThreadNewAndRunParamsToolResourcesCodeInterpreter
1598 return param.MarshalObject(r, (*shadow)(&r))
1511 return param.MarshalObject(r, (*shadow)(&r))
1599}
1512}
1513+func (r *BetaThreadNewAndRunParamsToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error {
1514+ return apijson.UnmarshalRoot(data, r)
1515+}
1600
1516
1601type BetaThreadNewAndRunParamsToolResourcesFileSearch struct {
1517type BetaThreadNewAndRunParamsToolResourcesFileSearch struct {
1602 // The ID of the
1518 // The ID of the
@@ -1607,72 +1523,12 @@ type BetaThreadNewAndRunParamsToolResourcesFileSearch struct {
1607 paramObj
1523 paramObj
1608}
1524}
1609
1525
1610−// IsPresent returns true if the field's value is not omitted and not the JSON
1611−// "null". To check if this field is omitted, use [param.IsOmitted].
1612−func (f BetaThreadNewAndRunParamsToolResourcesFileSearch) IsPresent() bool {
1613− return !param.IsOmitted(f) && !f.IsNull()
1614−}
1615func (r BetaThreadNewAndRunParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1526func (r BetaThreadNewAndRunParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) {
1616 type shadow BetaThreadNewAndRunParamsToolResourcesFileSearch
1527 type shadow BetaThreadNewAndRunParamsToolResourcesFileSearch
1617 return param.MarshalObject(r, (*shadow)(&r))
1528 return param.MarshalObject(r, (*shadow)(&r))
1618}
1529}
1619−
1530+func (r *BetaThreadNewAndRunParamsToolResourcesFileSearch) UnmarshalJSON(data []byte) error {
1620−// Only one field can be non-zero.
1531+ return apijson.UnmarshalRoot(data, r)
1621−//
1622−// Use [param.IsOmitted] to confirm if a field is set.
1623−type BetaThreadNewAndRunParamsToolUnion struct {
1624− OfCodeInterpreterTool *CodeInterpreterToolParam `json:",omitzero,inline"`
1625− OfFileSearchTool *FileSearchToolParam `json:",omitzero,inline"`
1626− OfFunctionTool *FunctionToolParam `json:",omitzero,inline"`
1627− paramUnion
1628−}
1629−
1630−// IsPresent returns true if the field's value is not omitted and not the JSON
1631−// "null". To check if this field is omitted, use [param.IsOmitted].
1632−func (u BetaThreadNewAndRunParamsToolUnion) IsPresent() bool {
1633− return !param.IsOmitted(u) && !u.IsNull()
1634−}
1635−func (u BetaThreadNewAndRunParamsToolUnion) MarshalJSON() ([]byte, error) {
1636− return param.MarshalUnion[BetaThreadNewAndRunParamsToolUnion](u.OfCodeInterpreterTool, u.OfFileSearchTool, u.OfFunctionTool)
1637−}
1638−
1639−func (u *BetaThreadNewAndRunParamsToolUnion) asAny() any {
1640− if !param.IsOmitted(u.OfCodeInterpreterTool) {
1641− return u.OfCodeInterpreterTool
1642− } else if !param.IsOmitted(u.OfFileSearchTool) {
1643− return u.OfFileSearchTool
1644− } else if !param.IsOmitted(u.OfFunctionTool) {
1645− return u.OfFunctionTool
1646− }
1647− return nil
1648−}
1649−
1650−// Returns a pointer to the underlying variant's property, if present.
1651−func (u BetaThreadNewAndRunParamsToolUnion) GetFileSearch() *FileSearchToolFileSearchParam {
1652− if vt := u.OfFileSearchTool; vt != nil {
1653− return &vt.FileSearch
1654− }
1655− return nil
1656−}
1657−
1658−// Returns a pointer to the underlying variant's property, if present.
1659−func (u BetaThreadNewAndRunParamsToolUnion) GetFunction() *shared.FunctionDefinitionParam {
1660− if vt := u.OfFunctionTool; vt != nil {
1661− return &vt.Function
1662− }
1663− return nil
1664−}
1665−
1666−// Returns a pointer to the underlying variant's property, if present.
1667−func (u BetaThreadNewAndRunParamsToolUnion) GetType() *string {
1668− if vt := u.OfCodeInterpreterTool; vt != nil {
1669− return (*string)(&vt.Type)
1670− } else if vt := u.OfFileSearchTool; vt != nil {
1671− return (*string)(&vt.Type)
1672− } else if vt := u.OfFunctionTool; vt != nil {
1673− return (*string)(&vt.Type)
1674− }
1675− return nil
1676}
1532}
1677
1533
1678// Controls for how a thread will be truncated prior to the run. Use this to
1534// Controls for how a thread will be truncated prior to the run. Use this to
@@ -1693,18 +1549,16 @@ type BetaThreadNewAndRunParamsTruncationStrategy struct {
1693 paramObj
1549 paramObj
1694}
1550}
1695
1551
1696−// IsPresent returns true if the field's value is not omitted and not the JSON
1697−// "null". To check if this field is omitted, use [param.IsOmitted].
1698−func (f BetaThreadNewAndRunParamsTruncationStrategy) IsPresent() bool {
1699− return !param.IsOmitted(f) && !f.IsNull()
1700−}
1701func (r BetaThreadNewAndRunParamsTruncationStrategy) MarshalJSON() (data []byte, err error) {
1552func (r BetaThreadNewAndRunParamsTruncationStrategy) MarshalJSON() (data []byte, err error) {
1702 type shadow BetaThreadNewAndRunParamsTruncationStrategy
1553 type shadow BetaThreadNewAndRunParamsTruncationStrategy
1703 return param.MarshalObject(r, (*shadow)(&r))
1554 return param.MarshalObject(r, (*shadow)(&r))
1704}
1555}
1556+func (r *BetaThreadNewAndRunParamsTruncationStrategy) UnmarshalJSON(data []byte) error {
1557+ return apijson.UnmarshalRoot(data, r)
1558+}
1705
1559
1706func init() {
1560func init() {
1707 apijson.RegisterFieldValidator[BetaThreadNewAndRunParamsTruncationStrategy](
1561 apijson.RegisterFieldValidator[BetaThreadNewAndRunParamsTruncationStrategy](
1708− "Type", false, "auto", "last_messages",
1562+ "type", "auto", "last_messages",
1709 )
1563 )
1710}
1564}
vendor/github.com/openai/openai-go/betathreadmessage.go+308−313
@@ -9,7 +9,6 @@ import (
9 "fmt"
9 "fmt"
10 "net/http"
10 "net/http"
11 "net/url"
11 "net/url"
12− "reflect"
13
12
14 "github.com/openai/openai-go/internal/apijson"
13 "github.com/openai/openai-go/internal/apijson"
15 "github.com/openai/openai-go/internal/apiquery"
14 "github.com/openai/openai-go/internal/apiquery"
@@ -17,10 +16,9 @@ import (
17 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/option"
18 "github.com/openai/openai-go/packages/pagination"
17 "github.com/openai/openai-go/packages/pagination"
19 "github.com/openai/openai-go/packages/param"
18 "github.com/openai/openai-go/packages/param"
20− "github.com/openai/openai-go/packages/resp"
19+ "github.com/openai/openai-go/packages/respjson"
21 "github.com/openai/openai-go/shared"
20 "github.com/openai/openai-go/shared"
22 "github.com/openai/openai-go/shared/constant"
21 "github.com/openai/openai-go/shared/constant"
23− "github.com/tidwall/gjson"
24)
22)
25
23
26// BetaThreadMessageService contains methods and other services that help with
24// BetaThreadMessageService contains methods and other services that help with
@@ -29,6 +27,8 @@ import (
29// Note, unlike clients, this service does not read variables from the environment
27// Note, unlike clients, this service does not read variables from the environment
30// automatically. You should not instantiate this service directly, and instead use
28// automatically. You should not instantiate this service directly, and instead use
31// the [NewBetaThreadMessageService] method instead.
29// the [NewBetaThreadMessageService] method instead.
30+//
31+// Deprecated: The Assistants API is deprecated in favor of the Responses API
32type BetaThreadMessageService struct {
32type BetaThreadMessageService struct {
33 Options []option.RequestOption
33 Options []option.RequestOption
34}
34}
@@ -43,6 +43,8 @@ func NewBetaThreadMessageService(opts ...option.RequestOption) (r BetaThreadMess
43}
43}
44
44
45// Create a message.
45// Create a message.
46+//
47+// Deprecated: The Assistants API is deprecated in favor of the Responses API
46func (r *BetaThreadMessageService) New(ctx context.Context, threadID string, body BetaThreadMessageNewParams, opts ...option.RequestOption) (res *Message, err error) {
48func (r *BetaThreadMessageService) New(ctx context.Context, threadID string, body BetaThreadMessageNewParams, opts ...option.RequestOption) (res *Message, err error) {
47 opts = append(r.Options[:], opts...)
49 opts = append(r.Options[:], opts...)
48 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
50 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -56,6 +58,8 @@ func (r *BetaThreadMessageService) New(ctx context.Context, threadID string, bod
56}
58}
57
59
58// Retrieve a message.
60// Retrieve a message.
61+//
62+// Deprecated: The Assistants API is deprecated in favor of the Responses API
59func (r *BetaThreadMessageService) Get(ctx context.Context, threadID string, messageID string, opts ...option.RequestOption) (res *Message, err error) {
63func (r *BetaThreadMessageService) Get(ctx context.Context, threadID string, messageID string, opts ...option.RequestOption) (res *Message, err error) {
60 opts = append(r.Options[:], opts...)
64 opts = append(r.Options[:], opts...)
61 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
65 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -73,6 +77,8 @@ func (r *BetaThreadMessageService) Get(ctx context.Context, threadID string, mes
73}
77}
74
78
75// Modifies a message.
79// Modifies a message.
80+//
81+// Deprecated: The Assistants API is deprecated in favor of the Responses API
76func (r *BetaThreadMessageService) Update(ctx context.Context, threadID string, messageID string, body BetaThreadMessageUpdateParams, opts ...option.RequestOption) (res *Message, err error) {
82func (r *BetaThreadMessageService) Update(ctx context.Context, threadID string, messageID string, body BetaThreadMessageUpdateParams, opts ...option.RequestOption) (res *Message, err error) {
77 opts = append(r.Options[:], opts...)
83 opts = append(r.Options[:], opts...)
78 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
84 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -90,6 +96,8 @@ func (r *BetaThreadMessageService) Update(ctx context.Context, threadID string,
90}
96}
91
97
92// Returns a list of messages for a given thread.
98// Returns a list of messages for a given thread.
99+//
100+// Deprecated: The Assistants API is deprecated in favor of the Responses API
93func (r *BetaThreadMessageService) List(ctx context.Context, threadID string, query BetaThreadMessageListParams, opts ...option.RequestOption) (res *pagination.CursorPage[Message], err error) {
101func (r *BetaThreadMessageService) List(ctx context.Context, threadID string, query BetaThreadMessageListParams, opts ...option.RequestOption) (res *pagination.CursorPage[Message], err error) {
94 var raw *http.Response
102 var raw *http.Response
95 opts = append(r.Options[:], opts...)
103 opts = append(r.Options[:], opts...)
@@ -112,11 +120,15 @@ func (r *BetaThreadMessageService) List(ctx context.Context, threadID string, qu
112}
120}
113
121
114// Returns a list of messages for a given thread.
122// Returns a list of messages for a given thread.
123+//
124+// Deprecated: The Assistants API is deprecated in favor of the Responses API
115func (r *BetaThreadMessageService) ListAutoPaging(ctx context.Context, threadID string, query BetaThreadMessageListParams, opts ...option.RequestOption) *pagination.CursorPageAutoPager[Message] {
125func (r *BetaThreadMessageService) ListAutoPaging(ctx context.Context, threadID string, query BetaThreadMessageListParams, opts ...option.RequestOption) *pagination.CursorPageAutoPager[Message] {
116 return pagination.NewCursorPageAutoPager(r.List(ctx, threadID, query, opts...))
126 return pagination.NewCursorPageAutoPager(r.List(ctx, threadID, query, opts...))
117}
127}
118
128
119// Deletes a message.
129// Deletes a message.
130+//
131+// Deprecated: The Assistants API is deprecated in favor of the Responses API
120func (r *BetaThreadMessageService) Delete(ctx context.Context, threadID string, messageID string, opts ...option.RequestOption) (res *MessageDeleted, err error) {
132func (r *BetaThreadMessageService) Delete(ctx context.Context, threadID string, messageID string, opts ...option.RequestOption) (res *MessageDeleted, err error) {
121 opts = append(r.Options[:], opts...)
133 opts = append(r.Options[:], opts...)
122 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
134 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -150,25 +162,34 @@ type AnnotationUnion struct {
150 // This field is from variant [FilePathAnnotation].
162 // This field is from variant [FilePathAnnotation].
151 FilePath FilePathAnnotationFilePath `json:"file_path"`
163 FilePath FilePathAnnotationFilePath `json:"file_path"`
152 JSON struct {
164 JSON struct {
153− EndIndex resp.Field
165+ EndIndex respjson.Field
154− FileCitation resp.Field
166+ FileCitation respjson.Field
155− StartIndex resp.Field
167+ StartIndex respjson.Field
156− Text resp.Field
168+ Text respjson.Field
157− Type resp.Field
169+ Type respjson.Field
158− FilePath resp.Field
170+ FilePath respjson.Field
159 raw string
171 raw string
160 } `json:"-"`
172 } `json:"-"`
161}
173}
162
174
175+// anyAnnotation is implemented by each variant of [AnnotationUnion] to add type
176+// safety for the return type of [AnnotationUnion.AsAny]
177+type anyAnnotation interface {
178+ implAnnotationUnion()
179+}
180+
181+func (FileCitationAnnotation) implAnnotationUnion() {}
182+func (FilePathAnnotation) implAnnotationUnion() {}
183+
163// Use the following switch statement to find the correct variant
184// Use the following switch statement to find the correct variant
164//
185//
165// switch variant := AnnotationUnion.AsAny().(type) {
186// switch variant := AnnotationUnion.AsAny().(type) {
166−// case FileCitationAnnotation:
187+// case openai.FileCitationAnnotation:
167−// case FilePathAnnotation:
188+// case openai.FilePathAnnotation:
168// default:
189// default:
169// fmt.Errorf("no variant present")
190// fmt.Errorf("no variant present")
170// }
191// }
171−func (u AnnotationUnion) AsAny() any {
192+func (u AnnotationUnion) AsAny() anyAnnotation {
172 switch u.Type {
193 switch u.Type {
173 case "file_citation":
194 case "file_citation":
174 return u.AsFileCitation()
195 return u.AsFileCitation()
@@ -213,26 +234,35 @@ type AnnotationDeltaUnion struct {
213 // This field is from variant [FilePathDeltaAnnotation].
234 // This field is from variant [FilePathDeltaAnnotation].
214 FilePath FilePathDeltaAnnotationFilePath `json:"file_path"`
235 FilePath FilePathDeltaAnnotationFilePath `json:"file_path"`
215 JSON struct {
236 JSON struct {
216− Index resp.Field
237+ Index respjson.Field
217− Type resp.Field
238+ Type respjson.Field
218− EndIndex resp.Field
239+ EndIndex respjson.Field
219− FileCitation resp.Field
240+ FileCitation respjson.Field
220− StartIndex resp.Field
241+ StartIndex respjson.Field
221− Text resp.Field
242+ Text respjson.Field
222− FilePath resp.Field
243+ FilePath respjson.Field
223 raw string
244 raw string
224 } `json:"-"`
245 } `json:"-"`
225}
246}
226
247
248+// anyAnnotationDelta is implemented by each variant of [AnnotationDeltaUnion] to
249+// add type safety for the return type of [AnnotationDeltaUnion.AsAny]
250+type anyAnnotationDelta interface {
251+ implAnnotationDeltaUnion()
252+}
253+
254+func (FileCitationDeltaAnnotation) implAnnotationDeltaUnion() {}
255+func (FilePathDeltaAnnotation) implAnnotationDeltaUnion() {}
256+
227// Use the following switch statement to find the correct variant
257// Use the following switch statement to find the correct variant
228//
258//
229// switch variant := AnnotationDeltaUnion.AsAny().(type) {
259// switch variant := AnnotationDeltaUnion.AsAny().(type) {
230−// case FileCitationDeltaAnnotation:
260+// case openai.FileCitationDeltaAnnotation:
231−// case FilePathDeltaAnnotation:
261+// case openai.FilePathDeltaAnnotation:
232// default:
262// default:
233// fmt.Errorf("no variant present")
263// fmt.Errorf("no variant present")
234// }
264// }
235−func (u AnnotationDeltaUnion) AsAny() any {
265+func (u AnnotationDeltaUnion) AsAny() anyAnnotationDelta {
236 switch u.Type {
266 switch u.Type {
237 case "file_citation":
267 case "file_citation":
238 return u.AsFileCitation()
268 return u.AsFileCitation()
@@ -270,15 +300,14 @@ type FileCitationAnnotation struct {
270 Text string `json:"text,required"`
300 Text string `json:"text,required"`
271 // Always `file_citation`.
301 // Always `file_citation`.
272 Type constant.FileCitation `json:"type,required"`
302 Type constant.FileCitation `json:"type,required"`
273− // Metadata for the response, check the presence of optional fields with the
303+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
274− // [resp.Field.IsPresent] method.
275 JSON struct {
304 JSON struct {
276− EndIndex resp.Field
305+ EndIndex respjson.Field
277− FileCitation resp.Field
306+ FileCitation respjson.Field
278− StartIndex resp.Field
307+ StartIndex respjson.Field
279− Text resp.Field
308+ Text respjson.Field
280− Type resp.Field
309+ Type respjson.Field
281− ExtraFields map[string]resp.Field
310+ ExtraFields map[string]respjson.Field
282 raw string
311 raw string
283 } `json:"-"`
312 } `json:"-"`
284}
313}
@@ -292,11 +321,10 @@ func (r *FileCitationAnnotation) UnmarshalJSON(data []byte) error {
292type FileCitationAnnotationFileCitation struct {
321type FileCitationAnnotationFileCitation struct {
293 // The ID of the specific File the citation is from.
322 // The ID of the specific File the citation is from.
294 FileID string `json:"file_id,required"`
323 FileID string `json:"file_id,required"`
295− // Metadata for the response, check the presence of optional fields with the
324+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
296− // [resp.Field.IsPresent] method.
297 JSON struct {
325 JSON struct {
298− FileID resp.Field
326+ FileID respjson.Field
299− ExtraFields map[string]resp.Field
327+ ExtraFields map[string]respjson.Field
300 raw string
328 raw string
301 } `json:"-"`
329 } `json:"-"`
302}
330}
@@ -320,16 +348,15 @@ type FileCitationDeltaAnnotation struct {
320 StartIndex int64 `json:"start_index"`
348 StartIndex int64 `json:"start_index"`
321 // The text in the message content that needs to be replaced.
349 // The text in the message content that needs to be replaced.
322 Text string `json:"text"`
350 Text string `json:"text"`
323− // Metadata for the response, check the presence of optional fields with the
351+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
324− // [resp.Field.IsPresent] method.
325 JSON struct {
352 JSON struct {
326− Index resp.Field
353+ Index respjson.Field
327− Type resp.Field
354+ Type respjson.Field
328− EndIndex resp.Field
355+ EndIndex respjson.Field
329− FileCitation resp.Field
356+ FileCitation respjson.Field
330− StartIndex resp.Field
357+ StartIndex respjson.Field
331− Text resp.Field
358+ Text respjson.Field
332− ExtraFields map[string]resp.Field
359+ ExtraFields map[string]respjson.Field
333 raw string
360 raw string
334 } `json:"-"`
361 } `json:"-"`
335}
362}
@@ -345,12 +372,11 @@ type FileCitationDeltaAnnotationFileCitation struct {
345 FileID string `json:"file_id"`
372 FileID string `json:"file_id"`
346 // The specific quote in the file.
373 // The specific quote in the file.
347 Quote string `json:"quote"`
374 Quote string `json:"quote"`
348− // Metadata for the response, check the presence of optional fields with the
375+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
349− // [resp.Field.IsPresent] method.
350 JSON struct {
376 JSON struct {
351− FileID resp.Field
377+ FileID respjson.Field
352− Quote resp.Field
378+ Quote respjson.Field
353− ExtraFields map[string]resp.Field
379+ ExtraFields map[string]respjson.Field
354 raw string
380 raw string
355 } `json:"-"`
381 } `json:"-"`
356}
382}
@@ -371,15 +397,14 @@ type FilePathAnnotation struct {
371 Text string `json:"text,required"`
397 Text string `json:"text,required"`
372 // Always `file_path`.
398 // Always `file_path`.
373 Type constant.FilePath `json:"type,required"`
399 Type constant.FilePath `json:"type,required"`
374− // Metadata for the response, check the presence of optional fields with the
400+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
375− // [resp.Field.IsPresent] method.
376 JSON struct {
401 JSON struct {
377− EndIndex resp.Field
402+ EndIndex respjson.Field
378− FilePath resp.Field
403+ FilePath respjson.Field
379− StartIndex resp.Field
404+ StartIndex respjson.Field
380− Text resp.Field
405+ Text respjson.Field
381− Type resp.Field
406+ Type respjson.Field
382− ExtraFields map[string]resp.Field
407+ ExtraFields map[string]respjson.Field
383 raw string
408 raw string
384 } `json:"-"`
409 } `json:"-"`
385}
410}
@@ -393,11 +418,10 @@ func (r *FilePathAnnotation) UnmarshalJSON(data []byte) error {
393type FilePathAnnotationFilePath struct {
418type FilePathAnnotationFilePath struct {
394 // The ID of the file that was generated.
419 // The ID of the file that was generated.
395 FileID string `json:"file_id,required"`
420 FileID string `json:"file_id,required"`
396− // Metadata for the response, check the presence of optional fields with the
421+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
397− // [resp.Field.IsPresent] method.
398 JSON struct {
422 JSON struct {
399− FileID resp.Field
423+ FileID respjson.Field
400− ExtraFields map[string]resp.Field
424+ ExtraFields map[string]respjson.Field
401 raw string
425 raw string
402 } `json:"-"`
426 } `json:"-"`
403}
427}
@@ -420,16 +444,15 @@ type FilePathDeltaAnnotation struct {
420 StartIndex int64 `json:"start_index"`
444 StartIndex int64 `json:"start_index"`
421 // The text in the message content that needs to be replaced.
445 // The text in the message content that needs to be replaced.
422 Text string `json:"text"`
446 Text string `json:"text"`
423− // Metadata for the response, check the presence of optional fields with the
447+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
424− // [resp.Field.IsPresent] method.
425 JSON struct {
448 JSON struct {
426− Index resp.Field
449+ Index respjson.Field
427− Type resp.Field
450+ Type respjson.Field
428− EndIndex resp.Field
451+ EndIndex respjson.Field
429− FilePath resp.Field
452+ FilePath respjson.Field
430− StartIndex resp.Field
453+ StartIndex respjson.Field
431− Text resp.Field
454+ Text respjson.Field
432− ExtraFields map[string]resp.Field
455+ ExtraFields map[string]respjson.Field
433 raw string
456 raw string
434 } `json:"-"`
457 } `json:"-"`
435}
458}
@@ -443,11 +466,10 @@ func (r *FilePathDeltaAnnotation) UnmarshalJSON(data []byte) error {
443type FilePathDeltaAnnotationFilePath struct {
466type FilePathDeltaAnnotationFilePath struct {
444 // The ID of the file that was generated.
467 // The ID of the file that was generated.
445 FileID string `json:"file_id"`
468 FileID string `json:"file_id"`
446− // Metadata for the response, check the presence of optional fields with the
469+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
447− // [resp.Field.IsPresent] method.
448 JSON struct {
470 JSON struct {
449− FileID resp.Field
471+ FileID respjson.Field
450− ExtraFields map[string]resp.Field
472+ ExtraFields map[string]respjson.Field
451 raw string
473 raw string
452 } `json:"-"`
474 } `json:"-"`
453}
475}
@@ -468,12 +490,11 @@ type ImageFile struct {
468 //
490 //
469 // Any of "auto", "low", "high".
491 // Any of "auto", "low", "high".
470 Detail ImageFileDetail `json:"detail"`
492 Detail ImageFileDetail `json:"detail"`
471− // Metadata for the response, check the presence of optional fields with the
493+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
472− // [resp.Field.IsPresent] method.
473 JSON struct {
494 JSON struct {
474− FileID resp.Field
495+ FileID respjson.Field
475− Detail resp.Field
496+ Detail respjson.Field
476− ExtraFields map[string]resp.Field
497+ ExtraFields map[string]respjson.Field
477 raw string
498 raw string
478 } `json:"-"`
499 } `json:"-"`
479}
500}
@@ -488,9 +509,9 @@ func (r *ImageFile) UnmarshalJSON(data []byte) error {
488//
509//
489// Warning: the fields of the param type will not be present. ToParam should only
510// Warning: the fields of the param type will not be present. ToParam should only
490// be used at the last possible moment before sending a request. Test for this with
511// be used at the last possible moment before sending a request. Test for this with
491−// ImageFileParam.IsOverridden()
512+// ImageFileParam.Overrides()
492func (r ImageFile) ToParam() ImageFileParam {
513func (r ImageFile) ToParam() ImageFileParam {
493− return param.OverrideObj[ImageFileParam](r.RawJSON())
514+ return param.Override[ImageFileParam](json.RawMessage(r.RawJSON()))
494}
515}
495
516
496// Specifies the detail level of the image if specified by the user. `low` uses
517// Specifies the detail level of the image if specified by the user. `low` uses
@@ -517,13 +538,13 @@ type ImageFileParam struct {
517 paramObj
538 paramObj
518}
539}
519
540
520−// IsPresent returns true if the field's value is not omitted and not the JSON
521−// "null". To check if this field is omitted, use [param.IsOmitted].
522−func (f ImageFileParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
523func (r ImageFileParam) MarshalJSON() (data []byte, err error) {
541func (r ImageFileParam) MarshalJSON() (data []byte, err error) {
524 type shadow ImageFileParam
542 type shadow ImageFileParam
525 return param.MarshalObject(r, (*shadow)(&r))
543 return param.MarshalObject(r, (*shadow)(&r))
526}
544}
545+func (r *ImageFileParam) UnmarshalJSON(data []byte) error {
546+ return apijson.UnmarshalRoot(data, r)
547+}
527
548
528// References an image [File](https://platform.openai.com/docs/api-reference/files)
549// References an image [File](https://platform.openai.com/docs/api-reference/files)
529// in the content of a message.
550// in the content of a message.
@@ -531,12 +552,11 @@ type ImageFileContentBlock struct {
531 ImageFile ImageFile `json:"image_file,required"`
552 ImageFile ImageFile `json:"image_file,required"`
532 // Always `image_file`.
553 // Always `image_file`.
533 Type constant.ImageFile `json:"type,required"`
554 Type constant.ImageFile `json:"type,required"`
534− // Metadata for the response, check the presence of optional fields with the
555+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
535− // [resp.Field.IsPresent] method.
536 JSON struct {
556 JSON struct {
537− ImageFile resp.Field
557+ ImageFile respjson.Field
538− Type resp.Field
558+ Type respjson.Field
539− ExtraFields map[string]resp.Field
559+ ExtraFields map[string]respjson.Field
540 raw string
560 raw string
541 } `json:"-"`
561 } `json:"-"`
542}
562}
@@ -551,9 +571,9 @@ func (r *ImageFileContentBlock) UnmarshalJSON(data []byte) error {
551//
571//
552// Warning: the fields of the param type will not be present. ToParam should only
572// Warning: the fields of the param type will not be present. ToParam should only
553// be used at the last possible moment before sending a request. Test for this with
573// be used at the last possible moment before sending a request. Test for this with
554−// ImageFileContentBlockParam.IsOverridden()
574+// ImageFileContentBlockParam.Overrides()
555func (r ImageFileContentBlock) ToParam() ImageFileContentBlockParam {
575func (r ImageFileContentBlock) ToParam() ImageFileContentBlockParam {
556− return param.OverrideObj[ImageFileContentBlockParam](r.RawJSON())
576+ return param.Override[ImageFileContentBlockParam](json.RawMessage(r.RawJSON()))
557}
577}
558
578
559// References an image [File](https://platform.openai.com/docs/api-reference/files)
579// References an image [File](https://platform.openai.com/docs/api-reference/files)
@@ -569,13 +589,13 @@ type ImageFileContentBlockParam struct {
569 paramObj
589 paramObj
570}
590}
571
591
572−// IsPresent returns true if the field's value is not omitted and not the JSON
573−// "null". To check if this field is omitted, use [param.IsOmitted].
574−func (f ImageFileContentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
575func (r ImageFileContentBlockParam) MarshalJSON() (data []byte, err error) {
592func (r ImageFileContentBlockParam) MarshalJSON() (data []byte, err error) {
576 type shadow ImageFileContentBlockParam
593 type shadow ImageFileContentBlockParam
577 return param.MarshalObject(r, (*shadow)(&r))
594 return param.MarshalObject(r, (*shadow)(&r))
578}
595}
596+func (r *ImageFileContentBlockParam) UnmarshalJSON(data []byte) error {
597+ return apijson.UnmarshalRoot(data, r)
598+}
579
599
580type ImageFileDelta struct {
600type ImageFileDelta struct {
581 // Specifies the detail level of the image if specified by the user. `low` uses
601 // Specifies the detail level of the image if specified by the user. `low` uses
@@ -587,12 +607,11 @@ type ImageFileDelta struct {
587 // in the message content. Set `purpose="vision"` when uploading the File if you
607 // in the message content. Set `purpose="vision"` when uploading the File if you
588 // need to later display the file content.
608 // need to later display the file content.
589 FileID string `json:"file_id"`
609 FileID string `json:"file_id"`
590− // Metadata for the response, check the presence of optional fields with the
610+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
591− // [resp.Field.IsPresent] method.
592 JSON struct {
611 JSON struct {
593− Detail resp.Field
612+ Detail respjson.Field
594− FileID resp.Field
613+ FileID respjson.Field
595− ExtraFields map[string]resp.Field
614+ ExtraFields map[string]respjson.Field
596 raw string
615 raw string
597 } `json:"-"`
616 } `json:"-"`
598}
617}
@@ -621,13 +640,12 @@ type ImageFileDeltaBlock struct {
621 // Always `image_file`.
640 // Always `image_file`.
622 Type constant.ImageFile `json:"type,required"`
641 Type constant.ImageFile `json:"type,required"`
623 ImageFile ImageFileDelta `json:"image_file"`
642 ImageFile ImageFileDelta `json:"image_file"`
624− // Metadata for the response, check the presence of optional fields with the
643+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
625− // [resp.Field.IsPresent] method.
626 JSON struct {
644 JSON struct {
627− Index resp.Field
645+ Index respjson.Field
628− Type resp.Field
646+ Type respjson.Field
629− ImageFile resp.Field
647+ ImageFile respjson.Field
630− ExtraFields map[string]resp.Field
648+ ExtraFields map[string]respjson.Field
631 raw string
649 raw string
632 } `json:"-"`
650 } `json:"-"`
633}
651}
@@ -647,12 +665,11 @@ type ImageURL struct {
647 //
665 //
648 // Any of "auto", "low", "high".
666 // Any of "auto", "low", "high".
649 Detail ImageURLDetail `json:"detail"`
667 Detail ImageURLDetail `json:"detail"`
650− // Metadata for the response, check the presence of optional fields with the
668+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
651− // [resp.Field.IsPresent] method.
652 JSON struct {
669 JSON struct {
653− URL resp.Field
670+ URL respjson.Field
654− Detail resp.Field
671+ Detail respjson.Field
655− ExtraFields map[string]resp.Field
672+ ExtraFields map[string]respjson.Field
656 raw string
673 raw string
657 } `json:"-"`
674 } `json:"-"`
658}
675}
@@ -667,9 +684,9 @@ func (r *ImageURL) UnmarshalJSON(data []byte) error {
667//
684//
668// Warning: the fields of the param type will not be present. ToParam should only
685// Warning: the fields of the param type will not be present. ToParam should only
669// be used at the last possible moment before sending a request. Test for this with
686// be used at the last possible moment before sending a request. Test for this with
670−// ImageURLParam.IsOverridden()
687+// ImageURLParam.Overrides()
671func (r ImageURL) ToParam() ImageURLParam {
688func (r ImageURL) ToParam() ImageURLParam {
672− return param.OverrideObj[ImageURLParam](r.RawJSON())
689+ return param.Override[ImageURLParam](json.RawMessage(r.RawJSON()))
673}
690}
674
691
675// Specifies the detail level of the image. `low` uses fewer tokens, you can opt in
692// Specifies the detail level of the image. `low` uses fewer tokens, you can opt in
@@ -695,25 +712,24 @@ type ImageURLParam struct {
695 paramObj
712 paramObj
696}
713}
697
714
698−// IsPresent returns true if the field's value is not omitted and not the JSON
699−// "null". To check if this field is omitted, use [param.IsOmitted].
700−func (f ImageURLParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
701func (r ImageURLParam) MarshalJSON() (data []byte, err error) {
715func (r ImageURLParam) MarshalJSON() (data []byte, err error) {
702 type shadow ImageURLParam
716 type shadow ImageURLParam
703 return param.MarshalObject(r, (*shadow)(&r))
717 return param.MarshalObject(r, (*shadow)(&r))
704}
718}
719+func (r *ImageURLParam) UnmarshalJSON(data []byte) error {
720+ return apijson.UnmarshalRoot(data, r)
721+}
705
722
706// References an image URL in the content of a message.
723// References an image URL in the content of a message.
707type ImageURLContentBlock struct {
724type ImageURLContentBlock struct {
708 ImageURL ImageURL `json:"image_url,required"`
725 ImageURL ImageURL `json:"image_url,required"`
709 // The type of the content part.
726 // The type of the content part.
710 Type constant.ImageURL `json:"type,required"`
727 Type constant.ImageURL `json:"type,required"`
711− // Metadata for the response, check the presence of optional fields with the
728+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
712− // [resp.Field.IsPresent] method.
713 JSON struct {
729 JSON struct {
714− ImageURL resp.Field
730+ ImageURL respjson.Field
715− Type resp.Field
731+ Type respjson.Field
716− ExtraFields map[string]resp.Field
732+ ExtraFields map[string]respjson.Field
717 raw string
733 raw string
718 } `json:"-"`
734 } `json:"-"`
719}
735}
@@ -728,9 +744,9 @@ func (r *ImageURLContentBlock) UnmarshalJSON(data []byte) error {
728//
744//
729// Warning: the fields of the param type will not be present. ToParam should only
745// Warning: the fields of the param type will not be present. ToParam should only
730// be used at the last possible moment before sending a request. Test for this with
746// be used at the last possible moment before sending a request. Test for this with
731−// ImageURLContentBlockParam.IsOverridden()
747+// ImageURLContentBlockParam.Overrides()
732func (r ImageURLContentBlock) ToParam() ImageURLContentBlockParam {
748func (r ImageURLContentBlock) ToParam() ImageURLContentBlockParam {
733− return param.OverrideObj[ImageURLContentBlockParam](r.RawJSON())
749+ return param.Override[ImageURLContentBlockParam](json.RawMessage(r.RawJSON()))
734}
750}
735
751
736// References an image URL in the content of a message.
752// References an image URL in the content of a message.
@@ -745,13 +761,13 @@ type ImageURLContentBlockParam struct {
745 paramObj
761 paramObj
746}
762}
747
763
748−// IsPresent returns true if the field's value is not omitted and not the JSON
749−// "null". To check if this field is omitted, use [param.IsOmitted].
750−func (f ImageURLContentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
751func (r ImageURLContentBlockParam) MarshalJSON() (data []byte, err error) {
764func (r ImageURLContentBlockParam) MarshalJSON() (data []byte, err error) {
752 type shadow ImageURLContentBlockParam
765 type shadow ImageURLContentBlockParam
753 return param.MarshalObject(r, (*shadow)(&r))
766 return param.MarshalObject(r, (*shadow)(&r))
754}
767}
768+func (r *ImageURLContentBlockParam) UnmarshalJSON(data []byte) error {
769+ return apijson.UnmarshalRoot(data, r)
770+}
755
771
756type ImageURLDelta struct {
772type ImageURLDelta struct {
757 // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in
773 // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in
@@ -762,12 +778,11 @@ type ImageURLDelta struct {
762 // The URL of the image, must be a supported image types: jpeg, jpg, png, gif,
778 // The URL of the image, must be a supported image types: jpeg, jpg, png, gif,
763 // webp.
779 // webp.
764 URL string `json:"url"`
780 URL string `json:"url"`
765− // Metadata for the response, check the presence of optional fields with the
781+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
766− // [resp.Field.IsPresent] method.
767 JSON struct {
782 JSON struct {
768− Detail resp.Field
783+ Detail respjson.Field
769− URL resp.Field
784+ URL respjson.Field
770− ExtraFields map[string]resp.Field
785+ ExtraFields map[string]respjson.Field
771 raw string
786 raw string
772 } `json:"-"`
787 } `json:"-"`
773}
788}
@@ -795,13 +810,12 @@ type ImageURLDeltaBlock struct {
795 // Always `image_url`.
810 // Always `image_url`.
796 Type constant.ImageURL `json:"type,required"`
811 Type constant.ImageURL `json:"type,required"`
797 ImageURL ImageURLDelta `json:"image_url"`
812 ImageURL ImageURLDelta `json:"image_url"`
798− // Metadata for the response, check the presence of optional fields with the
813+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
799− // [resp.Field.IsPresent] method.
800 JSON struct {
814 JSON struct {
801− Index resp.Field
815+ Index respjson.Field
802− Type resp.Field
816+ Type respjson.Field
803− ImageURL resp.Field
817+ ImageURL respjson.Field
804− ExtraFields map[string]resp.Field
818+ ExtraFields map[string]respjson.Field
805 raw string
819 raw string
806 } `json:"-"`
820 } `json:"-"`
807}
821}
@@ -858,24 +872,23 @@ type Message struct {
858 // The [thread](https://platform.openai.com/docs/api-reference/threads) ID that
872 // The [thread](https://platform.openai.com/docs/api-reference/threads) ID that
859 // this message belongs to.
873 // this message belongs to.
860 ThreadID string `json:"thread_id,required"`
874 ThreadID string `json:"thread_id,required"`
861− // Metadata for the response, check the presence of optional fields with the
875+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
862− // [resp.Field.IsPresent] method.
863 JSON struct {
876 JSON struct {
864− ID resp.Field
877+ ID respjson.Field
865− AssistantID resp.Field
878+ AssistantID respjson.Field
866− Attachments resp.Field
879+ Attachments respjson.Field
867− CompletedAt resp.Field
880+ CompletedAt respjson.Field
868− Content resp.Field
881+ Content respjson.Field
869− CreatedAt resp.Field
882+ CreatedAt respjson.Field
870− IncompleteAt resp.Field
883+ IncompleteAt respjson.Field
871− IncompleteDetails resp.Field
884+ IncompleteDetails respjson.Field
872− Metadata resp.Field
885+ Metadata respjson.Field
873− Object resp.Field
886+ Object respjson.Field
874− Role resp.Field
887+ Role respjson.Field
875− RunID resp.Field
888+ RunID respjson.Field
876− Status resp.Field
889+ Status respjson.Field
877− ThreadID resp.Field
890+ ThreadID respjson.Field
878− ExtraFields map[string]resp.Field
891+ ExtraFields map[string]respjson.Field
879 raw string
892 raw string
880 } `json:"-"`
893 } `json:"-"`
881}
894}
@@ -891,12 +904,11 @@ type MessageAttachment struct {
891 FileID string `json:"file_id"`
904 FileID string `json:"file_id"`
892 // The tools to add this file to.
905 // The tools to add this file to.
893 Tools []MessageAttachmentToolUnion `json:"tools"`
906 Tools []MessageAttachmentToolUnion `json:"tools"`
894− // Metadata for the response, check the presence of optional fields with the
907+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
895− // [resp.Field.IsPresent] method.
896 JSON struct {
908 JSON struct {
897− FileID resp.Field
909+ FileID respjson.Field
898− Tools resp.Field
910+ Tools respjson.Field
899− ExtraFields map[string]resp.Field
911+ ExtraFields map[string]respjson.Field
900 raw string
912 raw string
901 } `json:"-"`
913 } `json:"-"`
902}
914}
@@ -908,13 +920,13 @@ func (r *MessageAttachment) UnmarshalJSON(data []byte) error {
908}
920}
909
921
910// MessageAttachmentToolUnion contains all possible properties and values from
922// MessageAttachmentToolUnion contains all possible properties and values from
911−// [CodeInterpreterTool], [MessageAttachmentToolAssistantToolsFileSearchTypeOnly].
923+// [CodeInterpreterTool], [MessageAttachmentToolFileSearchTool].
912//
924//
913// Use the methods beginning with 'As' to cast the union to one of its variants.
925// Use the methods beginning with 'As' to cast the union to one of its variants.
914type MessageAttachmentToolUnion struct {
926type MessageAttachmentToolUnion struct {
915 Type string `json:"type"`
927 Type string `json:"type"`
916 JSON struct {
928 JSON struct {
917− Type resp.Field
929+ Type respjson.Field
918 raw string
930 raw string
919 } `json:"-"`
931 } `json:"-"`
920}
932}
@@ -924,7 +936,7 @@ func (u MessageAttachmentToolUnion) AsCodeInterpreterTool() (v CodeInterpreterTo
924 return
936 return
925}
937}
926
938
927−func (u MessageAttachmentToolUnion) AsFileSearchTool() (v MessageAttachmentToolAssistantToolsFileSearchTypeOnly) {
939+func (u MessageAttachmentToolUnion) AsFileSearchTool() (v MessageAttachmentToolFileSearchTool) {
928 apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
940 apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
929 return
941 return
930}
942}
@@ -936,21 +948,20 @@ func (r *MessageAttachmentToolUnion) UnmarshalJSON(data []byte) error {
936 return apijson.UnmarshalRoot(data, r)
948 return apijson.UnmarshalRoot(data, r)
937}
949}
938
950
939−type MessageAttachmentToolAssistantToolsFileSearchTypeOnly struct {
951+type MessageAttachmentToolFileSearchTool struct {
940 // The type of tool being defined: `file_search`
952 // The type of tool being defined: `file_search`
941 Type constant.FileSearch `json:"type,required"`
953 Type constant.FileSearch `json:"type,required"`
942− // Metadata for the response, check the presence of optional fields with the
954+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
943− // [resp.Field.IsPresent] method.
944 JSON struct {
955 JSON struct {
945− Type resp.Field
956+ Type respjson.Field
946− ExtraFields map[string]resp.Field
957+ ExtraFields map[string]respjson.Field
947 raw string
958 raw string
948 } `json:"-"`
959 } `json:"-"`
949}
960}
950
961
951// Returns the unmodified JSON received from the API
962// Returns the unmodified JSON received from the API
952−func (r MessageAttachmentToolAssistantToolsFileSearchTypeOnly) RawJSON() string { return r.JSON.raw }
963+func (r MessageAttachmentToolFileSearchTool) RawJSON() string { return r.JSON.raw }
953−func (r *MessageAttachmentToolAssistantToolsFileSearchTypeOnly) UnmarshalJSON(data []byte) error {
964+func (r *MessageAttachmentToolFileSearchTool) UnmarshalJSON(data []byte) error {
954 return apijson.UnmarshalRoot(data, r)
965 return apijson.UnmarshalRoot(data, r)
955}
966}
956
967
@@ -961,11 +972,10 @@ type MessageIncompleteDetails struct {
961 // Any of "content_filter", "max_tokens", "run_cancelled", "run_expired",
972 // Any of "content_filter", "max_tokens", "run_cancelled", "run_expired",
962 // "run_failed".
973 // "run_failed".
963 Reason string `json:"reason,required"`
974 Reason string `json:"reason,required"`
964− // Metadata for the response, check the presence of optional fields with the
975+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
965− // [resp.Field.IsPresent] method.
966 JSON struct {
976 JSON struct {
967− Reason resp.Field
977+ Reason respjson.Field
968− ExtraFields map[string]resp.Field
978+ ExtraFields map[string]respjson.Field
969 raw string
979 raw string
970 } `json:"-"`
980 } `json:"-"`
971}
981}
@@ -1013,26 +1023,37 @@ type MessageContentUnion struct {
1013 // This field is from variant [RefusalContentBlock].
1023 // This field is from variant [RefusalContentBlock].
1014 Refusal string `json:"refusal"`
1024 Refusal string `json:"refusal"`
1015 JSON struct {
1025 JSON struct {
1016− ImageFile resp.Field
1026+ ImageFile respjson.Field
1017− Type resp.Field
1027+ Type respjson.Field
1018− ImageURL resp.Field
1028+ ImageURL respjson.Field
1019− Text resp.Field
1029+ Text respjson.Field
1020− Refusal resp.Field
1030+ Refusal respjson.Field
1021 raw string
1031 raw string
1022 } `json:"-"`
1032 } `json:"-"`
1023}
1033}
1024
1034
1035+// anyMessageContent is implemented by each variant of [MessageContentUnion] to add
1036+// type safety for the return type of [MessageContentUnion.AsAny]
1037+type anyMessageContent interface {
1038+ implMessageContentUnion()
1039+}
1040+
1041+func (ImageFileContentBlock) implMessageContentUnion() {}
1042+func (ImageURLContentBlock) implMessageContentUnion() {}
1043+func (TextContentBlock) implMessageContentUnion() {}
1044+func (RefusalContentBlock) implMessageContentUnion() {}
1045+
1025// Use the following switch statement to find the correct variant
1046// Use the following switch statement to find the correct variant
1026//
1047//
1027// switch variant := MessageContentUnion.AsAny().(type) {
1048// switch variant := MessageContentUnion.AsAny().(type) {
1028−// case ImageFileContentBlock:
1049+// case openai.ImageFileContentBlock:
1029−// case ImageURLContentBlock:
1050+// case openai.ImageURLContentBlock:
1030−// case TextContentBlock:
1051+// case openai.TextContentBlock:
1031−// case RefusalContentBlock:
1052+// case openai.RefusalContentBlock:
1032// default:
1053// default:
1033// fmt.Errorf("no variant present")
1054// fmt.Errorf("no variant present")
1034// }
1055// }
1035−func (u MessageContentUnion) AsAny() any {
1056+func (u MessageContentUnion) AsAny() anyMessageContent {
1036 switch u.Type {
1057 switch u.Type {
1037 case "image_file":
1058 case "image_file":
1038 return u.AsImageFile()
1059 return u.AsImageFile()
@@ -1093,27 +1114,39 @@ type MessageContentDeltaUnion struct {
1093 // This field is from variant [ImageURLDeltaBlock].
1114 // This field is from variant [ImageURLDeltaBlock].
1094 ImageURL ImageURLDelta `json:"image_url"`
1115 ImageURL ImageURLDelta `json:"image_url"`
1095 JSON struct {
1116 JSON struct {
1096− Index resp.Field
1117+ Index respjson.Field
1097− Type resp.Field
1118+ Type respjson.Field
1098− ImageFile resp.Field
1119+ ImageFile respjson.Field
1099− Text resp.Field
1120+ Text respjson.Field
1100− Refusal resp.Field
1121+ Refusal respjson.Field
1101− ImageURL resp.Field
1122+ ImageURL respjson.Field
1102 raw string
1123 raw string
1103 } `json:"-"`
1124 } `json:"-"`
1104}
1125}
1105
1126
1127+// anyMessageContentDelta is implemented by each variant of
1128+// [MessageContentDeltaUnion] to add type safety for the return type of
1129+// [MessageContentDeltaUnion.AsAny]
1130+type anyMessageContentDelta interface {
1131+ implMessageContentDeltaUnion()
1132+}
1133+
1134+func (ImageFileDeltaBlock) implMessageContentDeltaUnion() {}
1135+func (TextDeltaBlock) implMessageContentDeltaUnion() {}
1136+func (RefusalDeltaBlock) implMessageContentDeltaUnion() {}
1137+func (ImageURLDeltaBlock) implMessageContentDeltaUnion() {}
1138+
1106// Use the following switch statement to find the correct variant
1139// Use the following switch statement to find the correct variant
1107//
1140//
1108// switch variant := MessageContentDeltaUnion.AsAny().(type) {
1141// switch variant := MessageContentDeltaUnion.AsAny().(type) {
1109−// case ImageFileDeltaBlock:
1142+// case openai.ImageFileDeltaBlock:
1110−// case TextDeltaBlock:
1143+// case openai.TextDeltaBlock:
1111−// case RefusalDeltaBlock:
1144+// case openai.RefusalDeltaBlock:
1112−// case ImageURLDeltaBlock:
1145+// case openai.ImageURLDeltaBlock:
1113// default:
1146// default:
1114// fmt.Errorf("no variant present")
1147// fmt.Errorf("no variant present")
1115// }
1148// }
1116−func (u MessageContentDeltaUnion) AsAny() any {
1149+func (u MessageContentDeltaUnion) AsAny() anyMessageContentDelta {
1117 switch u.Type {
1150 switch u.Type {
1118 case "image_file":
1151 case "image_file":
1119 return u.AsImageFile()
1152 return u.AsImageFile()
@@ -1182,11 +1215,11 @@ type MessageContentPartParamUnion struct {
1182 paramUnion
1215 paramUnion
1183}
1216}
1184
1217
1185−// IsPresent returns true if the field's value is not omitted and not the JSON
1186−// "null". To check if this field is omitted, use [param.IsOmitted].
1187−func (u MessageContentPartParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
1188func (u MessageContentPartParamUnion) MarshalJSON() ([]byte, error) {
1218func (u MessageContentPartParamUnion) MarshalJSON() ([]byte, error) {
1189− return param.MarshalUnion[MessageContentPartParamUnion](u.OfImageFile, u.OfImageURL, u.OfText)
1219+ return param.MarshalUnion(u, u.OfImageFile, u.OfImageURL, u.OfText)
1220+}
1221+func (u *MessageContentPartParamUnion) UnmarshalJSON(data []byte) error {
1222+ return apijson.UnmarshalRoot(data, u)
1190}
1223}
1191
1224
1192func (u *MessageContentPartParamUnion) asAny() any {
1225func (u *MessageContentPartParamUnion) asAny() any {
@@ -1239,21 +1272,9 @@ func (u MessageContentPartParamUnion) GetType() *string {
1239func init() {
1272func init() {
1240 apijson.RegisterUnion[MessageContentPartParamUnion](
1273 apijson.RegisterUnion[MessageContentPartParamUnion](
1241 "type",
1274 "type",
1242− apijson.UnionVariant{
1243− TypeFilter: gjson.JSON,
1244− Type: reflect.TypeOf(ImageFileContentBlockParam{}),
1275+ apijson.Discriminator[ImageFileContentBlockParam]("image_file"),
1245− DiscriminatorValue: "image_file",
1246− },
1247− apijson.UnionVariant{
1248− TypeFilter: gjson.JSON,
1249− Type: reflect.TypeOf(ImageURLContentBlockParam{}),
1276+ apijson.Discriminator[ImageURLContentBlockParam]("image_url"),
1250− DiscriminatorValue: "image_url",
1251− },
1252− apijson.UnionVariant{
1253− TypeFilter: gjson.JSON,
1254− Type: reflect.TypeOf(TextContentBlockParam{}),
1277+ apijson.Discriminator[TextContentBlockParam]("text"),
1255− DiscriminatorValue: "text",
1256− },
1257 )
1278 )
1258}
1279}
1259
1280
@@ -1261,13 +1282,12 @@ type MessageDeleted struct {
1261 ID string `json:"id,required"`
1282 ID string `json:"id,required"`
1262 Deleted bool `json:"deleted,required"`
1283 Deleted bool `json:"deleted,required"`
1263 Object constant.ThreadMessageDeleted `json:"object,required"`
1284 Object constant.ThreadMessageDeleted `json:"object,required"`
1264− // Metadata for the response, check the presence of optional fields with the
1285+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1265− // [resp.Field.IsPresent] method.
1266 JSON struct {
1286 JSON struct {
1267− ID resp.Field
1287+ ID respjson.Field
1268− Deleted resp.Field
1288+ Deleted respjson.Field
1269− Object resp.Field
1289+ Object respjson.Field
1270− ExtraFields map[string]resp.Field
1290+ ExtraFields map[string]respjson.Field
1271 raw string
1291 raw string
1272 } `json:"-"`
1292 } `json:"-"`
1273}
1293}
@@ -1286,12 +1306,11 @@ type MessageDelta struct {
1286 //
1306 //
1287 // Any of "user", "assistant".
1307 // Any of "user", "assistant".
1288 Role MessageDeltaRole `json:"role"`
1308 Role MessageDeltaRole `json:"role"`
1289− // Metadata for the response, check the presence of optional fields with the
1309+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1290− // [resp.Field.IsPresent] method.
1291 JSON struct {
1310 JSON struct {
1292− Content resp.Field
1311+ Content respjson.Field
1293− Role resp.Field
1312+ Role respjson.Field
1294− ExtraFields map[string]resp.Field
1313+ ExtraFields map[string]respjson.Field
1295 raw string
1314 raw string
1296 } `json:"-"`
1315 } `json:"-"`
1297}
1316}
@@ -1319,13 +1338,12 @@ type MessageDeltaEvent struct {
1319 Delta MessageDelta `json:"delta,required"`
1338 Delta MessageDelta `json:"delta,required"`
1320 // The object type, which is always `thread.message.delta`.
1339 // The object type, which is always `thread.message.delta`.
1321 Object constant.ThreadMessageDelta `json:"object,required"`
1340 Object constant.ThreadMessageDelta `json:"object,required"`
1322− // Metadata for the response, check the presence of optional fields with the
1341+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1323− // [resp.Field.IsPresent] method.
1324 JSON struct {
1342 JSON struct {
1325− ID resp.Field
1343+ ID respjson.Field
1326− Delta resp.Field
1344+ Delta respjson.Field
1327− Object resp.Field
1345+ Object respjson.Field
1328− ExtraFields map[string]resp.Field
1346+ ExtraFields map[string]respjson.Field
1329 raw string
1347 raw string
1330 } `json:"-"`
1348 } `json:"-"`
1331}
1349}
@@ -1341,12 +1359,11 @@ type RefusalContentBlock struct {
1341 Refusal string `json:"refusal,required"`
1359 Refusal string `json:"refusal,required"`
1342 // Always `refusal`.
1360 // Always `refusal`.
1343 Type constant.Refusal `json:"type,required"`
1361 Type constant.Refusal `json:"type,required"`
1344− // Metadata for the response, check the presence of optional fields with the
1362+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1345− // [resp.Field.IsPresent] method.
1346 JSON struct {
1363 JSON struct {
1347− Refusal resp.Field
1364+ Refusal respjson.Field
1348− Type resp.Field
1365+ Type respjson.Field
1349− ExtraFields map[string]resp.Field
1366+ ExtraFields map[string]respjson.Field
1350 raw string
1367 raw string
1351 } `json:"-"`
1368 } `json:"-"`
1352}
1369}
@@ -1364,13 +1381,12 @@ type RefusalDeltaBlock struct {
1364 // Always `refusal`.
1381 // Always `refusal`.
1365 Type constant.Refusal `json:"type,required"`
1382 Type constant.Refusal `json:"type,required"`
1366 Refusal string `json:"refusal"`
1383 Refusal string `json:"refusal"`
1367− // Metadata for the response, check the presence of optional fields with the
1384+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1368− // [resp.Field.IsPresent] method.
1369 JSON struct {
1385 JSON struct {
1370− Index resp.Field
1386+ Index respjson.Field
1371− Type resp.Field
1387+ Type respjson.Field
1372− Refusal resp.Field
1388+ Refusal respjson.Field
1373− ExtraFields map[string]resp.Field
1389+ ExtraFields map[string]respjson.Field
1374 raw string
1390 raw string
1375 } `json:"-"`
1391 } `json:"-"`
1376}
1392}
@@ -1385,12 +1401,11 @@ type Text struct {
1385 Annotations []AnnotationUnion `json:"annotations,required"`
1401 Annotations []AnnotationUnion `json:"annotations,required"`
1386 // The data that makes up the text.
1402 // The data that makes up the text.
1387 Value string `json:"value,required"`
1403 Value string `json:"value,required"`
1388− // Metadata for the response, check the presence of optional fields with the
1404+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1389− // [resp.Field.IsPresent] method.
1390 JSON struct {
1405 JSON struct {
1391− Annotations resp.Field
1406+ Annotations respjson.Field
1392− Value resp.Field
1407+ Value respjson.Field
1393− ExtraFields map[string]resp.Field
1408+ ExtraFields map[string]respjson.Field
1394 raw string
1409 raw string
1395 } `json:"-"`
1410 } `json:"-"`
1396}
1411}
@@ -1406,12 +1421,11 @@ type TextContentBlock struct {
1406 Text Text `json:"text,required"`
1421 Text Text `json:"text,required"`
1407 // Always `text`.
1422 // Always `text`.
1408 Type constant.Text `json:"type,required"`
1423 Type constant.Text `json:"type,required"`
1409− // Metadata for the response, check the presence of optional fields with the
1424+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1410− // [resp.Field.IsPresent] method.
1411 JSON struct {
1425 JSON struct {
1412− Text resp.Field
1426+ Text respjson.Field
1413− Type resp.Field
1427+ Type respjson.Field
1414− ExtraFields map[string]resp.Field
1428+ ExtraFields map[string]respjson.Field
1415 raw string
1429 raw string
1416 } `json:"-"`
1430 } `json:"-"`
1417}
1431}
@@ -1435,24 +1449,23 @@ type TextContentBlockParam struct {
1435 paramObj
1449 paramObj
1436}
1450}
1437
1451
1438−// IsPresent returns true if the field's value is not omitted and not the JSON
1439−// "null". To check if this field is omitted, use [param.IsOmitted].
1440−func (f TextContentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1441func (r TextContentBlockParam) MarshalJSON() (data []byte, err error) {
1452func (r TextContentBlockParam) MarshalJSON() (data []byte, err error) {
1442 type shadow TextContentBlockParam
1453 type shadow TextContentBlockParam
1443 return param.MarshalObject(r, (*shadow)(&r))
1454 return param.MarshalObject(r, (*shadow)(&r))
1444}
1455}
1456+func (r *TextContentBlockParam) UnmarshalJSON(data []byte) error {
1457+ return apijson.UnmarshalRoot(data, r)
1458+}
1445
1459
1446type TextDelta struct {
1460type TextDelta struct {
1447 Annotations []AnnotationDeltaUnion `json:"annotations"`
1461 Annotations []AnnotationDeltaUnion `json:"annotations"`
1448 // The data that makes up the text.
1462 // The data that makes up the text.
1449 Value string `json:"value"`
1463 Value string `json:"value"`
1450− // Metadata for the response, check the presence of optional fields with the
1464+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1451− // [resp.Field.IsPresent] method.
1452 JSON struct {
1465 JSON struct {
1453− Annotations resp.Field
1466+ Annotations respjson.Field
1454− Value resp.Field
1467+ Value respjson.Field
1455− ExtraFields map[string]resp.Field
1468+ ExtraFields map[string]respjson.Field
1456 raw string
1469 raw string
1457 } `json:"-"`
1470 } `json:"-"`
1458}
1471}
@@ -1470,13 +1483,12 @@ type TextDeltaBlock struct {
1470 // Always `text`.
1483 // Always `text`.
1471 Type constant.Text `json:"type,required"`
1484 Type constant.Text `json:"type,required"`
1472 Text TextDelta `json:"text"`
1485 Text TextDelta `json:"text"`
1473− // Metadata for the response, check the presence of optional fields with the
1486+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1474− // [resp.Field.IsPresent] method.
1475 JSON struct {
1487 JSON struct {
1476− Index resp.Field
1488+ Index respjson.Field
1477− Type resp.Field
1489+ Type respjson.Field
1478− Text resp.Field
1490+ Text respjson.Field
1479− ExtraFields map[string]resp.Field
1491+ ExtraFields map[string]respjson.Field
1480 raw string
1492 raw string
1481 } `json:"-"`
1493 } `json:"-"`
1482}
1494}
@@ -1507,18 +1519,17 @@ type BetaThreadMessageNewParams struct {
1507 //
1519 //
1508 // Keys are strings with a maximum length of 64 characters. Values are strings with
1520 // Keys are strings with a maximum length of 64 characters. Values are strings with
1509 // a maximum length of 512 characters.
1521 // a maximum length of 512 characters.
1510− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1522+ Metadata shared.Metadata `json:"metadata,omitzero"`
1511 paramObj
1523 paramObj
1512}
1524}
1513
1525
1514−// IsPresent returns true if the field's value is not omitted and not the JSON
1515−// "null". To check if this field is omitted, use [param.IsOmitted].
1516−func (f BetaThreadMessageNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1517−
1518func (r BetaThreadMessageNewParams) MarshalJSON() (data []byte, err error) {
1526func (r BetaThreadMessageNewParams) MarshalJSON() (data []byte, err error) {
1519 type shadow BetaThreadMessageNewParams
1527 type shadow BetaThreadMessageNewParams
1520 return param.MarshalObject(r, (*shadow)(&r))
1528 return param.MarshalObject(r, (*shadow)(&r))
1521}
1529}
1530+func (r *BetaThreadMessageNewParams) UnmarshalJSON(data []byte) error {
1531+ return apijson.UnmarshalRoot(data, r)
1532+}
1522
1533
1523// Only one field can be non-zero.
1534// Only one field can be non-zero.
1524//
1535//
@@ -1529,13 +1540,11 @@ type BetaThreadMessageNewParamsContentUnion struct {
1529 paramUnion
1540 paramUnion
1530}
1541}
1531
1542
1532−// IsPresent returns true if the field's value is not omitted and not the JSON
1533−// "null". To check if this field is omitted, use [param.IsOmitted].
1534−func (u BetaThreadMessageNewParamsContentUnion) IsPresent() bool {
1535− return !param.IsOmitted(u) && !u.IsNull()
1536−}
1537func (u BetaThreadMessageNewParamsContentUnion) MarshalJSON() ([]byte, error) {
1543func (u BetaThreadMessageNewParamsContentUnion) MarshalJSON() ([]byte, error) {
1544+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
1545+}
1538− return param.MarshalUnion[BetaThreadMessageNewParamsContentUnion](u.OfString, u.OfArrayOfContentParts)
1546+func (u *BetaThreadMessageNewParamsContentUnion) UnmarshalJSON(data []byte) error {
1547+ return apijson.UnmarshalRoot(data, u)
1539}
1548}
1540
1549
1541func (u *BetaThreadMessageNewParamsContentUnion) asAny() any {
1550func (u *BetaThreadMessageNewParamsContentUnion) asAny() any {
@@ -1568,15 +1577,13 @@ type BetaThreadMessageNewParamsAttachment struct {
1568 paramObj
1577 paramObj
1569}
1578}
1570
1579
1571−// IsPresent returns true if the field's value is not omitted and not the JSON
1572−// "null". To check if this field is omitted, use [param.IsOmitted].
1573−func (f BetaThreadMessageNewParamsAttachment) IsPresent() bool {
1574− return !param.IsOmitted(f) && !f.IsNull()
1575−}
1576func (r BetaThreadMessageNewParamsAttachment) MarshalJSON() (data []byte, err error) {
1580func (r BetaThreadMessageNewParamsAttachment) MarshalJSON() (data []byte, err error) {
1577 type shadow BetaThreadMessageNewParamsAttachment
1581 type shadow BetaThreadMessageNewParamsAttachment
1578 return param.MarshalObject(r, (*shadow)(&r))
1582 return param.MarshalObject(r, (*shadow)(&r))
1579}
1583}
1584+func (r *BetaThreadMessageNewParamsAttachment) UnmarshalJSON(data []byte) error {
1585+ return apijson.UnmarshalRoot(data, r)
1586+}
1580
1587
1581// Only one field can be non-zero.
1588// Only one field can be non-zero.
1582//
1589//
@@ -1587,13 +1594,11 @@ type BetaThreadMessageNewParamsAttachmentToolUnion struct {
1587 paramUnion
1594 paramUnion
1588}
1595}
1589
1596
1590−// IsPresent returns true if the field's value is not omitted and not the JSON
1591−// "null". To check if this field is omitted, use [param.IsOmitted].
1592−func (u BetaThreadMessageNewParamsAttachmentToolUnion) IsPresent() bool {
1593− return !param.IsOmitted(u) && !u.IsNull()
1594−}
1595func (u BetaThreadMessageNewParamsAttachmentToolUnion) MarshalJSON() ([]byte, error) {
1597func (u BetaThreadMessageNewParamsAttachmentToolUnion) MarshalJSON() ([]byte, error) {
1598+ return param.MarshalUnion(u, u.OfCodeInterpreter, u.OfFileSearch)
1599+}
1596− return param.MarshalUnion[BetaThreadMessageNewParamsAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch)
1600+func (u *BetaThreadMessageNewParamsAttachmentToolUnion) UnmarshalJSON(data []byte) error {
1601+ return apijson.UnmarshalRoot(data, u)
1597}
1602}
1598
1603
1599func (u *BetaThreadMessageNewParamsAttachmentToolUnion) asAny() any {
1604func (u *BetaThreadMessageNewParamsAttachmentToolUnion) asAny() any {
@@ -1618,37 +1623,32 @@ func (u BetaThreadMessageNewParamsAttachmentToolUnion) GetType() *string {
1618func init() {
1623func init() {
1619 apijson.RegisterUnion[BetaThreadMessageNewParamsAttachmentToolUnion](
1624 apijson.RegisterUnion[BetaThreadMessageNewParamsAttachmentToolUnion](
1620 "type",
1625 "type",
1621− apijson.UnionVariant{
1622− TypeFilter: gjson.JSON,
1623− Type: reflect.TypeOf(CodeInterpreterToolParam{}),
1626+ apijson.Discriminator[CodeInterpreterToolParam]("code_interpreter"),
1624− DiscriminatorValue: "code_interpreter",
1625− },
1626− apijson.UnionVariant{
1627− TypeFilter: gjson.JSON,
1628− Type: reflect.TypeOf(BetaThreadMessageNewParamsAttachmentToolFileSearch{}),
1627+ apijson.Discriminator[BetaThreadMessageNewParamsAttachmentToolFileSearch]("file_search"),
1629− DiscriminatorValue: "file_search",
1630− },
1631 )
1628 )
1632}
1629}
1633
1630
1634−// The property Type is required.
1631+func NewBetaThreadMessageNewParamsAttachmentToolFileSearch() BetaThreadMessageNewParamsAttachmentToolFileSearch {
1632+ return BetaThreadMessageNewParamsAttachmentToolFileSearch{
1633+ Type: "file_search",
1634+ }
1635+}
1636+
1637+// This struct has a constant value, construct it with
1638+// [NewBetaThreadMessageNewParamsAttachmentToolFileSearch].
1635type BetaThreadMessageNewParamsAttachmentToolFileSearch struct {
1639type BetaThreadMessageNewParamsAttachmentToolFileSearch struct {
1636 // The type of tool being defined: `file_search`
1640 // The type of tool being defined: `file_search`
1637− //
1638− // This field can be elided, and will marshal its zero value as "file_search".
1639 Type constant.FileSearch `json:"type,required"`
1641 Type constant.FileSearch `json:"type,required"`
1640 paramObj
1642 paramObj
1641}
1643}
1642
1644
1643−// IsPresent returns true if the field's value is not omitted and not the JSON
1644−// "null". To check if this field is omitted, use [param.IsOmitted].
1645−func (f BetaThreadMessageNewParamsAttachmentToolFileSearch) IsPresent() bool {
1646− return !param.IsOmitted(f) && !f.IsNull()
1647−}
1648func (r BetaThreadMessageNewParamsAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
1645func (r BetaThreadMessageNewParamsAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
1649 type shadow BetaThreadMessageNewParamsAttachmentToolFileSearch
1646 type shadow BetaThreadMessageNewParamsAttachmentToolFileSearch
1650 return param.MarshalObject(r, (*shadow)(&r))
1647 return param.MarshalObject(r, (*shadow)(&r))
1651}
1648}
1649+func (r *BetaThreadMessageNewParamsAttachmentToolFileSearch) UnmarshalJSON(data []byte) error {
1650+ return apijson.UnmarshalRoot(data, r)
1651+}
1652
1652
1653type BetaThreadMessageUpdateParams struct {
1653type BetaThreadMessageUpdateParams struct {
1654 // Set of 16 key-value pairs that can be attached to an object. This can be useful
1654 // Set of 16 key-value pairs that can be attached to an object. This can be useful
@@ -1657,18 +1657,17 @@ type BetaThreadMessageUpdateParams struct {
1657 //
1657 //
1658 // Keys are strings with a maximum length of 64 characters. Values are strings with
1658 // Keys are strings with a maximum length of 64 characters. Values are strings with
1659 // a maximum length of 512 characters.
1659 // a maximum length of 512 characters.
1660− Metadata shared.MetadataParam `json:"metadata,omitzero"`
1660+ Metadata shared.Metadata `json:"metadata,omitzero"`
1661 paramObj
1661 paramObj
1662}
1662}
1663
1663
1664−// IsPresent returns true if the field's value is not omitted and not the JSON
1665−// "null". To check if this field is omitted, use [param.IsOmitted].
1666−func (f BetaThreadMessageUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1667−
1668func (r BetaThreadMessageUpdateParams) MarshalJSON() (data []byte, err error) {
1664func (r BetaThreadMessageUpdateParams) MarshalJSON() (data []byte, err error) {
1669 type shadow BetaThreadMessageUpdateParams
1665 type shadow BetaThreadMessageUpdateParams
1670 return param.MarshalObject(r, (*shadow)(&r))
1666 return param.MarshalObject(r, (*shadow)(&r))
1671}
1667}
1668+func (r *BetaThreadMessageUpdateParams) UnmarshalJSON(data []byte) error {
1669+ return apijson.UnmarshalRoot(data, r)
1670+}
1672
1671
1673type BetaThreadMessageListParams struct {
1672type BetaThreadMessageListParams struct {
1674 // A cursor for use in pagination. `after` is an object ID that defines your place
1673 // A cursor for use in pagination. `after` is an object ID that defines your place
@@ -1694,13 +1693,9 @@ type BetaThreadMessageListParams struct {
1694 paramObj
1693 paramObj
1695}
1694}
1696
1695
1697−// IsPresent returns true if the field's value is not omitted and not the JSON
1698−// "null". To check if this field is omitted, use [param.IsOmitted].
1699−func (f BetaThreadMessageListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1700−
1701// URLQuery serializes [BetaThreadMessageListParams]'s query parameters as
1696// URLQuery serializes [BetaThreadMessageListParams]'s query parameters as
1702// `url.Values`.
1697// `url.Values`.
1703−func (r BetaThreadMessageListParams) URLQuery() (v url.Values) {
1698+func (r BetaThreadMessageListParams) URLQuery() (v url.Values, err error) {
1704 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
1699 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
1705 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
1700 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
1706 NestedFormat: apiquery.NestedQueryFormatBrackets,
1701 NestedFormat: apiquery.NestedQueryFormatBrackets,
vendor/github.com/openai/openai-go/betathreadrun.go+133−171
@@ -8,7 +8,6 @@ import (
8 "fmt"
8 "fmt"
9 "net/http"
9 "net/http"
10 "net/url"
10 "net/url"
11− "reflect"
12
11
13 "github.com/openai/openai-go/internal/apijson"
12 "github.com/openai/openai-go/internal/apijson"
14 "github.com/openai/openai-go/internal/apiquery"
13 "github.com/openai/openai-go/internal/apiquery"
@@ -16,11 +15,10 @@ import (
16 "github.com/openai/openai-go/option"
15 "github.com/openai/openai-go/option"
17 "github.com/openai/openai-go/packages/pagination"
16 "github.com/openai/openai-go/packages/pagination"
18 "github.com/openai/openai-go/packages/param"
17 "github.com/openai/openai-go/packages/param"
19− "github.com/openai/openai-go/packages/resp"
18+ "github.com/openai/openai-go/packages/respjson"
20 "github.com/openai/openai-go/packages/ssestream"
19 "github.com/openai/openai-go/packages/ssestream"
21 "github.com/openai/openai-go/shared"
20 "github.com/openai/openai-go/shared"
22 "github.com/openai/openai-go/shared/constant"
21 "github.com/openai/openai-go/shared/constant"
23− "github.com/tidwall/gjson"
24)
22)
25
23
26// BetaThreadRunService contains methods and other services that help with
24// BetaThreadRunService contains methods and other services that help with
@@ -29,9 +27,12 @@ import (
29// Note, unlike clients, this service does not read variables from the environment
27// Note, unlike clients, this service does not read variables from the environment
30// automatically. You should not instantiate this service directly, and instead use
28// automatically. You should not instantiate this service directly, and instead use
31// the [NewBetaThreadRunService] method instead.
29// the [NewBetaThreadRunService] method instead.
30+//
31+// Deprecated: The Assistants API is deprecated in favor of the Responses API
32type BetaThreadRunService struct {
32type BetaThreadRunService struct {
33 Options []option.RequestOption
33 Options []option.RequestOption
34+ // Deprecated: The Assistants API is deprecated in favor of the Responses API
34− Steps BetaThreadRunStepService
35+ Steps BetaThreadRunStepService
35}
36}
36
37
37// NewBetaThreadRunService generates a new service that applies the given options
38// NewBetaThreadRunService generates a new service that applies the given options
@@ -45,6 +46,8 @@ func NewBetaThreadRunService(opts ...option.RequestOption) (r BetaThreadRunServi
45}
46}
46
47
47// Create a run.
48// Create a run.
49+//
50+// Deprecated: The Assistants API is deprecated in favor of the Responses API
48func (r *BetaThreadRunService) New(ctx context.Context, threadID string, params BetaThreadRunNewParams, opts ...option.RequestOption) (res *Run, err error) {
51func (r *BetaThreadRunService) New(ctx context.Context, threadID string, params BetaThreadRunNewParams, opts ...option.RequestOption) (res *Run, err error) {
49 opts = append(r.Options[:], opts...)
52 opts = append(r.Options[:], opts...)
50 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
53 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -57,17 +60,9 @@ func (r *BetaThreadRunService) New(ctx context.Context, threadID string, params
57 return
60 return
58}
61}
59
62
60−// Create a run and poll until task is completed.
61−// Pass 0 to pollIntervalMs to use the default polling interval.
62−func (r *BetaThreadRunService) NewAndPoll(ctx context.Context, threadID string, params BetaThreadRunNewParams, pollIntervalMs int, opts ...option.RequestOption) (res *Run, err error) {
63− run, err := r.New(ctx, threadID, params, opts...)
64− if err != nil {
65− return nil, err
66− }
67− return r.PollStatus(ctx, threadID, run.ID, pollIntervalMs, opts...)
68−}
69−
70// Create a run.
63// Create a run.
64+//
65+// Deprecated: The Assistants API is deprecated in favor of the Responses API
71func (r *BetaThreadRunService) NewStreaming(ctx context.Context, threadID string, params BetaThreadRunNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) {
66func (r *BetaThreadRunService) NewStreaming(ctx context.Context, threadID string, params BetaThreadRunNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) {
72 var (
67 var (
73 raw *http.Response
68 raw *http.Response
@@ -85,6 +80,8 @@ func (r *BetaThreadRunService) NewStreaming(ctx context.Context, threadID string
85}
80}
86
81
87// Retrieves a run.
82// Retrieves a run.
83+//
84+// Deprecated: The Assistants API is deprecated in favor of the Responses API
88func (r *BetaThreadRunService) Get(ctx context.Context, threadID string, runID string, opts ...option.RequestOption) (res *Run, err error) {
85func (r *BetaThreadRunService) Get(ctx context.Context, threadID string, runID string, opts ...option.RequestOption) (res *Run, err error) {
89 opts = append(r.Options[:], opts...)
86 opts = append(r.Options[:], opts...)
90 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
87 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -102,6 +99,8 @@ func (r *BetaThreadRunService) Get(ctx context.Context, threadID string, runID s
102}
99}
103
100
104// Modifies a run.
101// Modifies a run.
102+//
103+// Deprecated: The Assistants API is deprecated in favor of the Responses API
105func (r *BetaThreadRunService) Update(ctx context.Context, threadID string, runID string, body BetaThreadRunUpdateParams, opts ...option.RequestOption) (res *Run, err error) {
104func (r *BetaThreadRunService) Update(ctx context.Context, threadID string, runID string, body BetaThreadRunUpdateParams, opts ...option.RequestOption) (res *Run, err error) {
106 opts = append(r.Options[:], opts...)
105 opts = append(r.Options[:], opts...)
107 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
106 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -119,6 +118,8 @@ func (r *BetaThreadRunService) Update(ctx context.Context, threadID string, runI
119}
118}
120
119
121// Returns a list of runs belonging to a thread.
120// Returns a list of runs belonging to a thread.
121+//
122+// Deprecated: The Assistants API is deprecated in favor of the Responses API
122func (r *BetaThreadRunService) List(ctx context.Context, threadID string, query BetaThreadRunListParams, opts ...option.RequestOption) (res *pagination.CursorPage[Run], err error) {
123func (r *BetaThreadRunService) List(ctx context.Context, threadID string, query BetaThreadRunListParams, opts ...option.RequestOption) (res *pagination.CursorPage[Run], err error) {
123 var raw *http.Response
124 var raw *http.Response
124 opts = append(r.Options[:], opts...)
125 opts = append(r.Options[:], opts...)
@@ -141,11 +142,15 @@ func (r *BetaThreadRunService) List(ctx context.Context, threadID string, query
141}
142}
142
143
143// Returns a list of runs belonging to a thread.
144// Returns a list of runs belonging to a thread.
145+//
146+// Deprecated: The Assistants API is deprecated in favor of the Responses API
144func (r *BetaThreadRunService) ListAutoPaging(ctx context.Context, threadID string, query BetaThreadRunListParams, opts ...option.RequestOption) *pagination.CursorPageAutoPager[Run] {
147func (r *BetaThreadRunService) ListAutoPaging(ctx context.Context, threadID string, query BetaThreadRunListParams, opts ...option.RequestOption) *pagination.CursorPageAutoPager[Run] {
145 return pagination.NewCursorPageAutoPager(r.List(ctx, threadID, query, opts...))
148 return pagination.NewCursorPageAutoPager(r.List(ctx, threadID, query, opts...))
146}
149}
147
150
148// Cancels a run that is `in_progress`.
151// Cancels a run that is `in_progress`.
152+//
153+// Deprecated: The Assistants API is deprecated in favor of the Responses API
149func (r *BetaThreadRunService) Cancel(ctx context.Context, threadID string, runID string, opts ...option.RequestOption) (res *Run, err error) {
154func (r *BetaThreadRunService) Cancel(ctx context.Context, threadID string, runID string, opts ...option.RequestOption) (res *Run, err error) {
150 opts = append(r.Options[:], opts...)
155 opts = append(r.Options[:], opts...)
151 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
156 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -166,6 +171,8 @@ func (r *BetaThreadRunService) Cancel(ctx context.Context, threadID string, runI
166// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the
171// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the
167// tool calls once they're all completed. All outputs must be submitted in a single
172// tool calls once they're all completed. All outputs must be submitted in a single
168// request.
173// request.
174+//
175+// Deprecated: The Assistants API is deprecated in favor of the Responses API
169func (r *BetaThreadRunService) SubmitToolOutputs(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, opts ...option.RequestOption) (res *Run, err error) {
176func (r *BetaThreadRunService) SubmitToolOutputs(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, opts ...option.RequestOption) (res *Run, err error) {
170 opts = append(r.Options[:], opts...)
177 opts = append(r.Options[:], opts...)
171 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
178 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -182,22 +189,12 @@ func (r *BetaThreadRunService) SubmitToolOutputs(ctx context.Context, threadID s
182 return
189 return
183}
190}
184
191
185−// A helper to submit a tool output to a run and poll for a terminal run state.
186−// Pass 0 to pollIntervalMs to use the default polling interval.
187−// More information on Run lifecycles can be found here:
188−// https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
189−func (r *BetaThreadRunService) SubmitToolOutputsAndPoll(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, pollIntervalMs int, opts ...option.RequestOption) (*Run, error) {
190− run, err := r.SubmitToolOutputs(ctx, threadID, runID, body, opts...)
191− if err != nil {
192− return nil, err
193− }
194− return r.PollStatus(ctx, threadID, run.ID, pollIntervalMs, opts...)
195−}
196−
197// When a run has the `status: "requires_action"` and `required_action.type` is
192// When a run has the `status: "requires_action"` and `required_action.type` is
198// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the
193// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the
199// tool calls once they're all completed. All outputs must be submitted in a single
194// tool calls once they're all completed. All outputs must be submitted in a single
200// request.
195// request.
196+//
197+// Deprecated: The Assistants API is deprecated in favor of the Responses API
201func (r *BetaThreadRunService) SubmitToolOutputsStreaming(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) {
198func (r *BetaThreadRunService) SubmitToolOutputsStreaming(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) {
202 var (
199 var (
203 raw *http.Response
200 raw *http.Response
@@ -230,13 +227,12 @@ type RequiredActionFunctionToolCall struct {
230 // The type of tool call the output is required for. For now, this is always
227 // The type of tool call the output is required for. For now, this is always
231 // `function`.
228 // `function`.
232 Type constant.Function `json:"type,required"`
229 Type constant.Function `json:"type,required"`
233− // Metadata for the response, check the presence of optional fields with the
230+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
234− // [resp.Field.IsPresent] method.
235 JSON struct {
231 JSON struct {
236− ID resp.Field
232+ ID respjson.Field
237− Function resp.Field
233+ Function respjson.Field
238− Type resp.Field
234+ Type respjson.Field
239− ExtraFields map[string]resp.Field
235+ ExtraFields map[string]respjson.Field
240 raw string
236 raw string
241 } `json:"-"`
237 } `json:"-"`
242}
238}
@@ -253,12 +249,11 @@ type RequiredActionFunctionToolCallFunction struct {
253 Arguments string `json:"arguments,required"`
249 Arguments string `json:"arguments,required"`
254 // The name of the function.
250 // The name of the function.
255 Name string `json:"name,required"`
251 Name string `json:"name,required"`
256− // Metadata for the response, check the presence of optional fields with the
252+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
257− // [resp.Field.IsPresent] method.
258 JSON struct {
253 JSON struct {
259− Arguments resp.Field
254+ Arguments respjson.Field
260− Name resp.Field
255+ Name respjson.Field
261− ExtraFields map[string]resp.Field
256+ ExtraFields map[string]respjson.Field
262 raw string
257 raw string
263 } `json:"-"`
258 } `json:"-"`
264}
259}
@@ -378,37 +373,36 @@ type Run struct {
378 Temperature float64 `json:"temperature,nullable"`
373 Temperature float64 `json:"temperature,nullable"`
379 // The nucleus sampling value used for this run. If not set, defaults to 1.
374 // The nucleus sampling value used for this run. If not set, defaults to 1.
380 TopP float64 `json:"top_p,nullable"`
375 TopP float64 `json:"top_p,nullable"`
381− // Metadata for the response, check the presence of optional fields with the
376+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
382− // [resp.Field.IsPresent] method.
383 JSON struct {
377 JSON struct {
384− ID resp.Field
378+ ID respjson.Field
385− AssistantID resp.Field
379+ AssistantID respjson.Field
386− CancelledAt resp.Field
380+ CancelledAt respjson.Field
387− CompletedAt resp.Field
381+ CompletedAt respjson.Field
388− CreatedAt resp.Field
382+ CreatedAt respjson.Field
389− ExpiresAt resp.Field
383+ ExpiresAt respjson.Field
390− FailedAt resp.Field
384+ FailedAt respjson.Field
391− IncompleteDetails resp.Field
385+ IncompleteDetails respjson.Field
392− Instructions resp.Field
386+ Instructions respjson.Field
393− LastError resp.Field
387+ LastError respjson.Field
394− MaxCompletionTokens resp.Field
388+ MaxCompletionTokens respjson.Field
395− MaxPromptTokens resp.Field
389+ MaxPromptTokens respjson.Field
396− Metadata resp.Field
390+ Metadata respjson.Field
397− Model resp.Field
391+ Model respjson.Field
398− Object resp.Field
392+ Object respjson.Field
399− ParallelToolCalls resp.Field
393+ ParallelToolCalls respjson.Field
400− RequiredAction resp.Field
394+ RequiredAction respjson.Field
401− ResponseFormat resp.Field
395+ ResponseFormat respjson.Field
402− StartedAt resp.Field
396+ StartedAt respjson.Field
403− Status resp.Field
397+ Status respjson.Field
404− ThreadID resp.Field
398+ ThreadID respjson.Field
405− ToolChoice resp.Field
399+ ToolChoice respjson.Field
406− Tools resp.Field
400+ Tools respjson.Field
407− TruncationStrategy resp.Field
401+ TruncationStrategy respjson.Field
408− Usage resp.Field
402+ Usage respjson.Field
409− Temperature resp.Field
403+ Temperature respjson.Field
410− TopP resp.Field
404+ TopP respjson.Field
411− ExtraFields map[string]resp.Field
405+ ExtraFields map[string]respjson.Field
412 raw string
406 raw string
413 } `json:"-"`
407 } `json:"-"`
414}
408}
@@ -427,11 +421,10 @@ type RunIncompleteDetails struct {
427 //
421 //
428 // Any of "max_completion_tokens", "max_prompt_tokens".
422 // Any of "max_completion_tokens", "max_prompt_tokens".
429 Reason string `json:"reason"`
423 Reason string `json:"reason"`
430− // Metadata for the response, check the presence of optional fields with the
424+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
431− // [resp.Field.IsPresent] method.
432 JSON struct {
425 JSON struct {
433− Reason resp.Field
426+ Reason respjson.Field
434− ExtraFields map[string]resp.Field
427+ ExtraFields map[string]respjson.Field
435 raw string
428 raw string
436 } `json:"-"`
429 } `json:"-"`
437}
430}
@@ -450,12 +443,11 @@ type RunLastError struct {
450 Code string `json:"code,required"`
443 Code string `json:"code,required"`
451 // A human-readable description of the error.
444 // A human-readable description of the error.
452 Message string `json:"message,required"`
445 Message string `json:"message,required"`
453− // Metadata for the response, check the presence of optional fields with the
446+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
454− // [resp.Field.IsPresent] method.
455 JSON struct {
447 JSON struct {
456− Code resp.Field
448+ Code respjson.Field
457− Message resp.Field
449+ Message respjson.Field
458− ExtraFields map[string]resp.Field
450+ ExtraFields map[string]respjson.Field
459 raw string
451 raw string
460 } `json:"-"`
452 } `json:"-"`
461}
453}
@@ -473,12 +465,11 @@ type RunRequiredAction struct {
473 SubmitToolOutputs RunRequiredActionSubmitToolOutputs `json:"submit_tool_outputs,required"`
465 SubmitToolOutputs RunRequiredActionSubmitToolOutputs `json:"submit_tool_outputs,required"`
474 // For now, this is always `submit_tool_outputs`.
466 // For now, this is always `submit_tool_outputs`.
475 Type constant.SubmitToolOutputs `json:"type,required"`
467 Type constant.SubmitToolOutputs `json:"type,required"`
476− // Metadata for the response, check the presence of optional fields with the
468+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
477− // [resp.Field.IsPresent] method.
478 JSON struct {
469 JSON struct {
479− SubmitToolOutputs resp.Field
470+ SubmitToolOutputs respjson.Field
480− Type resp.Field
471+ Type respjson.Field
481− ExtraFields map[string]resp.Field
472+ ExtraFields map[string]respjson.Field
482 raw string
473 raw string
483 } `json:"-"`
474 } `json:"-"`
484}
475}
@@ -493,11 +484,10 @@ func (r *RunRequiredAction) UnmarshalJSON(data []byte) error {
493type RunRequiredActionSubmitToolOutputs struct {
484type RunRequiredActionSubmitToolOutputs struct {
494 // A list of the relevant tool calls.
485 // A list of the relevant tool calls.
495 ToolCalls []RequiredActionFunctionToolCall `json:"tool_calls,required"`
486 ToolCalls []RequiredActionFunctionToolCall `json:"tool_calls,required"`
496− // Metadata for the response, check the presence of optional fields with the
487+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
497− // [resp.Field.IsPresent] method.
498 JSON struct {
488 JSON struct {
499− ToolCalls resp.Field
489+ ToolCalls respjson.Field
500− ExtraFields map[string]resp.Field
490+ ExtraFields map[string]respjson.Field
501 raw string
491 raw string
502 } `json:"-"`
492 } `json:"-"`
503}
493}
@@ -521,12 +511,11 @@ type RunTruncationStrategy struct {
521 // The number of most recent messages from the thread when constructing the context
511 // The number of most recent messages from the thread when constructing the context
522 // for the run.
512 // for the run.
523 LastMessages int64 `json:"last_messages,nullable"`
513 LastMessages int64 `json:"last_messages,nullable"`
524− // Metadata for the response, check the presence of optional fields with the
514+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
525− // [resp.Field.IsPresent] method.
526 JSON struct {
515 JSON struct {
527− Type resp.Field
516+ Type respjson.Field
528− LastMessages resp.Field
517+ LastMessages respjson.Field
529− ExtraFields map[string]resp.Field
518+ ExtraFields map[string]respjson.Field
530 raw string
519 raw string
531 } `json:"-"`
520 } `json:"-"`
532}
521}
@@ -546,13 +535,12 @@ type RunUsage struct {
546 PromptTokens int64 `json:"prompt_tokens,required"`
535 PromptTokens int64 `json:"prompt_tokens,required"`
547 // Total number of tokens used (prompt + completion).
536 // Total number of tokens used (prompt + completion).
548 TotalTokens int64 `json:"total_tokens,required"`
537 TotalTokens int64 `json:"total_tokens,required"`
549− // Metadata for the response, check the presence of optional fields with the
538+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
550− // [resp.Field.IsPresent] method.
551 JSON struct {
539 JSON struct {
552− CompletionTokens resp.Field
540+ CompletionTokens respjson.Field
553− PromptTokens resp.Field
541+ PromptTokens respjson.Field
554− TotalTokens resp.Field
542+ TotalTokens respjson.Field
555− ExtraFields map[string]resp.Field
543+ ExtraFields map[string]respjson.Field
556 raw string
544 raw string
557 } `json:"-"`
545 } `json:"-"`
558}
546}
@@ -627,7 +615,7 @@ type BetaThreadRunNewParams struct {
627 //
615 //
628 // Keys are strings with a maximum length of 64 characters. Values are strings with
616 // Keys are strings with a maximum length of 64 characters. Values are strings with
629 // a maximum length of 512 characters.
617 // a maximum length of 512 characters.
630− Metadata shared.MetadataParam `json:"metadata,omitzero"`
618+ Metadata shared.Metadata `json:"metadata,omitzero"`
631 // The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to
619 // The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to
632 // be used to execute this run. If a value is provided here, it will override the
620 // be used to execute this run. If a value is provided here, it will override the
633 // model associated with the assistant. If not, the model associated with the
621 // model associated with the assistant. If not, the model associated with the
@@ -688,17 +676,16 @@ type BetaThreadRunNewParams struct {
688 paramObj
676 paramObj
689}
677}
690
678
691−// IsPresent returns true if the field's value is not omitted and not the JSON
692−// "null". To check if this field is omitted, use [param.IsOmitted].
693−func (f BetaThreadRunNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
694−
695func (r BetaThreadRunNewParams) MarshalJSON() (data []byte, err error) {
679func (r BetaThreadRunNewParams) MarshalJSON() (data []byte, err error) {
696 type shadow BetaThreadRunNewParams
680 type shadow BetaThreadRunNewParams
697 return param.MarshalObject(r, (*shadow)(&r))
681 return param.MarshalObject(r, (*shadow)(&r))
698}
682}
683+func (r *BetaThreadRunNewParams) UnmarshalJSON(data []byte) error {
684+ return apijson.UnmarshalRoot(data, r)
685+}
699
686
700// URLQuery serializes [BetaThreadRunNewParams]'s query parameters as `url.Values`.
687// URLQuery serializes [BetaThreadRunNewParams]'s query parameters as `url.Values`.
701−func (r BetaThreadRunNewParams) URLQuery() (v url.Values) {
688+func (r BetaThreadRunNewParams) URLQuery() (v url.Values, err error) {
702 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
689 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
703 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
690 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
704 NestedFormat: apiquery.NestedQueryFormatBrackets,
691 NestedFormat: apiquery.NestedQueryFormatBrackets,
@@ -726,23 +713,21 @@ type BetaThreadRunNewParamsAdditionalMessage struct {
726 //
713 //
727 // Keys are strings with a maximum length of 64 characters. Values are strings with
714 // Keys are strings with a maximum length of 64 characters. Values are strings with
728 // a maximum length of 512 characters.
715 // a maximum length of 512 characters.
729− Metadata shared.MetadataParam `json:"metadata,omitzero"`
716+ Metadata shared.Metadata `json:"metadata,omitzero"`
730 paramObj
717 paramObj
731}
718}
732
719
733−// IsPresent returns true if the field's value is not omitted and not the JSON
734−// "null". To check if this field is omitted, use [param.IsOmitted].
735−func (f BetaThreadRunNewParamsAdditionalMessage) IsPresent() bool {
736− return !param.IsOmitted(f) && !f.IsNull()
737−}
738func (r BetaThreadRunNewParamsAdditionalMessage) MarshalJSON() (data []byte, err error) {
720func (r BetaThreadRunNewParamsAdditionalMessage) MarshalJSON() (data []byte, err error) {
739 type shadow BetaThreadRunNewParamsAdditionalMessage
721 type shadow BetaThreadRunNewParamsAdditionalMessage
740 return param.MarshalObject(r, (*shadow)(&r))
722 return param.MarshalObject(r, (*shadow)(&r))
741}
723}
724+func (r *BetaThreadRunNewParamsAdditionalMessage) UnmarshalJSON(data []byte) error {
725+ return apijson.UnmarshalRoot(data, r)
726+}
742
727
743func init() {
728func init() {
744 apijson.RegisterFieldValidator[BetaThreadRunNewParamsAdditionalMessage](
729 apijson.RegisterFieldValidator[BetaThreadRunNewParamsAdditionalMessage](
745− "Role", false, "user", "assistant",
730+ "role", "user", "assistant",
746 )
731 )
747}
732}
748
733
@@ -755,13 +740,11 @@ type BetaThreadRunNewParamsAdditionalMessageContentUnion struct {
755 paramUnion
740 paramUnion
756}
741}
757
742
758−// IsPresent returns true if the field's value is not omitted and not the JSON
759−// "null". To check if this field is omitted, use [param.IsOmitted].
760−func (u BetaThreadRunNewParamsAdditionalMessageContentUnion) IsPresent() bool {
761− return !param.IsOmitted(u) && !u.IsNull()
762−}
763func (u BetaThreadRunNewParamsAdditionalMessageContentUnion) MarshalJSON() ([]byte, error) {
743func (u BetaThreadRunNewParamsAdditionalMessageContentUnion) MarshalJSON() ([]byte, error) {
744+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
745+}
764− return param.MarshalUnion[BetaThreadRunNewParamsAdditionalMessageContentUnion](u.OfString, u.OfArrayOfContentParts)
746+func (u *BetaThreadRunNewParamsAdditionalMessageContentUnion) UnmarshalJSON(data []byte) error {
747+ return apijson.UnmarshalRoot(data, u)
765}
748}
766
749
767func (u *BetaThreadRunNewParamsAdditionalMessageContentUnion) asAny() any {
750func (u *BetaThreadRunNewParamsAdditionalMessageContentUnion) asAny() any {
@@ -781,15 +764,13 @@ type BetaThreadRunNewParamsAdditionalMessageAttachment struct {
781 paramObj
764 paramObj
782}
765}
783
766
784−// IsPresent returns true if the field's value is not omitted and not the JSON
785−// "null". To check if this field is omitted, use [param.IsOmitted].
786−func (f BetaThreadRunNewParamsAdditionalMessageAttachment) IsPresent() bool {
787− return !param.IsOmitted(f) && !f.IsNull()
788−}
789func (r BetaThreadRunNewParamsAdditionalMessageAttachment) MarshalJSON() (data []byte, err error) {
767func (r BetaThreadRunNewParamsAdditionalMessageAttachment) MarshalJSON() (data []byte, err error) {
790 type shadow BetaThreadRunNewParamsAdditionalMessageAttachment
768 type shadow BetaThreadRunNewParamsAdditionalMessageAttachment
791 return param.MarshalObject(r, (*shadow)(&r))
769 return param.MarshalObject(r, (*shadow)(&r))
792}
770}
771+func (r *BetaThreadRunNewParamsAdditionalMessageAttachment) UnmarshalJSON(data []byte) error {
772+ return apijson.UnmarshalRoot(data, r)
773+}
793
774
794// Only one field can be non-zero.
775// Only one field can be non-zero.
795//
776//
@@ -800,13 +781,11 @@ type BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion struct {
800 paramUnion
781 paramUnion
801}
782}
802
783
803−// IsPresent returns true if the field's value is not omitted and not the JSON
804−// "null". To check if this field is omitted, use [param.IsOmitted].
805−func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) IsPresent() bool {
806− return !param.IsOmitted(u) && !u.IsNull()
807−}
808func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) {
784func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) {
785+ return param.MarshalUnion(u, u.OfCodeInterpreter, u.OfFileSearch)
786+}
809− return param.MarshalUnion[BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch)
787+func (u *BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) UnmarshalJSON(data []byte) error {
788+ return apijson.UnmarshalRoot(data, u)
810}
789}
811
790
812func (u *BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) asAny() any {
791func (u *BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) asAny() any {
@@ -831,37 +810,32 @@ func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) GetType() *s
831func init() {
810func init() {
832 apijson.RegisterUnion[BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion](
811 apijson.RegisterUnion[BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion](
833 "type",
812 "type",
834− apijson.UnionVariant{
835− TypeFilter: gjson.JSON,
836− Type: reflect.TypeOf(CodeInterpreterToolParam{}),
813+ apijson.Discriminator[CodeInterpreterToolParam]("code_interpreter"),
837− DiscriminatorValue: "code_interpreter",
838− },
839− apijson.UnionVariant{
840− TypeFilter: gjson.JSON,
841− Type: reflect.TypeOf(BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch{}),
814+ apijson.Discriminator[BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch]("file_search"),
842− DiscriminatorValue: "file_search",
843− },
844 )
815 )
845}
816}
846
817
847−// The property Type is required.
818+func NewBetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch() BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch {
819+ return BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch{
820+ Type: "file_search",
821+ }
822+}
823+
824+// This struct has a constant value, construct it with
825+// [NewBetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch].
848type BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch struct {
826type BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch struct {
849 // The type of tool being defined: `file_search`
827 // The type of tool being defined: `file_search`
850− //
851− // This field can be elided, and will marshal its zero value as "file_search".
852 Type constant.FileSearch `json:"type,required"`
828 Type constant.FileSearch `json:"type,required"`
853 paramObj
829 paramObj
854}
830}
855
831
856−// IsPresent returns true if the field's value is not omitted and not the JSON
857−// "null". To check if this field is omitted, use [param.IsOmitted].
858−func (f BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch) IsPresent() bool {
859− return !param.IsOmitted(f) && !f.IsNull()
860−}
861func (r BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
832func (r BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) {
862 type shadow BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch
833 type shadow BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch
863 return param.MarshalObject(r, (*shadow)(&r))
834 return param.MarshalObject(r, (*shadow)(&r))
864}
835}
836+func (r *BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch) UnmarshalJSON(data []byte) error {
837+ return apijson.UnmarshalRoot(data, r)
838+}
865
839
866// Controls for how a thread will be truncated prior to the run. Use this to
840// Controls for how a thread will be truncated prior to the run. Use this to
867// control the intial context window of the run.
841// control the intial context window of the run.
@@ -881,19 +855,17 @@ type BetaThreadRunNewParamsTruncationStrategy struct {
881 paramObj
855 paramObj
882}
856}
883
857
884−// IsPresent returns true if the field's value is not omitted and not the JSON
885−// "null". To check if this field is omitted, use [param.IsOmitted].
886−func (f BetaThreadRunNewParamsTruncationStrategy) IsPresent() bool {
887− return !param.IsOmitted(f) && !f.IsNull()
888−}
889func (r BetaThreadRunNewParamsTruncationStrategy) MarshalJSON() (data []byte, err error) {
858func (r BetaThreadRunNewParamsTruncationStrategy) MarshalJSON() (data []byte, err error) {
890 type shadow BetaThreadRunNewParamsTruncationStrategy
859 type shadow BetaThreadRunNewParamsTruncationStrategy
891 return param.MarshalObject(r, (*shadow)(&r))
860 return param.MarshalObject(r, (*shadow)(&r))
892}
861}
862+func (r *BetaThreadRunNewParamsTruncationStrategy) UnmarshalJSON(data []byte) error {
863+ return apijson.UnmarshalRoot(data, r)
864+}
893
865
894func init() {
866func init() {
895 apijson.RegisterFieldValidator[BetaThreadRunNewParamsTruncationStrategy](
867 apijson.RegisterFieldValidator[BetaThreadRunNewParamsTruncationStrategy](
896− "Type", false, "auto", "last_messages",
868+ "type", "auto", "last_messages",
897 )
869 )
898}
870}
899
871
@@ -904,18 +876,17 @@ type BetaThreadRunUpdateParams struct {
904 //
876 //
905 // Keys are strings with a maximum length of 64 characters. Values are strings with
877 // Keys are strings with a maximum length of 64 characters. Values are strings with
906 // a maximum length of 512 characters.
878 // a maximum length of 512 characters.
907− Metadata shared.MetadataParam `json:"metadata,omitzero"`
879+ Metadata shared.Metadata `json:"metadata,omitzero"`
908 paramObj
880 paramObj
909}
881}
910
882
911−// IsPresent returns true if the field's value is not omitted and not the JSON
912−// "null". To check if this field is omitted, use [param.IsOmitted].
913−func (f BetaThreadRunUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
914−
915func (r BetaThreadRunUpdateParams) MarshalJSON() (data []byte, err error) {
883func (r BetaThreadRunUpdateParams) MarshalJSON() (data []byte, err error) {
916 type shadow BetaThreadRunUpdateParams
884 type shadow BetaThreadRunUpdateParams
917 return param.MarshalObject(r, (*shadow)(&r))
885 return param.MarshalObject(r, (*shadow)(&r))
918}
886}
887+func (r *BetaThreadRunUpdateParams) UnmarshalJSON(data []byte) error {
888+ return apijson.UnmarshalRoot(data, r)
889+}
919
890
920type BetaThreadRunListParams struct {
891type BetaThreadRunListParams struct {
921 // A cursor for use in pagination. `after` is an object ID that defines your place
892 // A cursor for use in pagination. `after` is an object ID that defines your place
@@ -939,13 +910,9 @@ type BetaThreadRunListParams struct {
939 paramObj
910 paramObj
940}
911}
941
912
942−// IsPresent returns true if the field's value is not omitted and not the JSON
943−// "null". To check if this field is omitted, use [param.IsOmitted].
944−func (f BetaThreadRunListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
945−
946// URLQuery serializes [BetaThreadRunListParams]'s query parameters as
913// URLQuery serializes [BetaThreadRunListParams]'s query parameters as
947// `url.Values`.
914// `url.Values`.
948−func (r BetaThreadRunListParams) URLQuery() (v url.Values) {
915+func (r BetaThreadRunListParams) URLQuery() (v url.Values, err error) {
949 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
916 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
950 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
917 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
951 NestedFormat: apiquery.NestedQueryFormatBrackets,
918 NestedFormat: apiquery.NestedQueryFormatBrackets,
@@ -967,16 +934,13 @@ type BetaThreadRunSubmitToolOutputsParams struct {
967 paramObj
934 paramObj
968}
935}
969
936
970−// IsPresent returns true if the field's value is not omitted and not the JSON
971−// "null". To check if this field is omitted, use [param.IsOmitted].
972−func (f BetaThreadRunSubmitToolOutputsParams) IsPresent() bool {
973− return !param.IsOmitted(f) && !f.IsNull()
974−}
975−
976func (r BetaThreadRunSubmitToolOutputsParams) MarshalJSON() (data []byte, err error) {
937func (r BetaThreadRunSubmitToolOutputsParams) MarshalJSON() (data []byte, err error) {
977 type shadow BetaThreadRunSubmitToolOutputsParams
938 type shadow BetaThreadRunSubmitToolOutputsParams
978 return param.MarshalObject(r, (*shadow)(&r))
939 return param.MarshalObject(r, (*shadow)(&r))
979}
940}
941+func (r *BetaThreadRunSubmitToolOutputsParams) UnmarshalJSON(data []byte) error {
942+ return apijson.UnmarshalRoot(data, r)
943+}
980
944
981type BetaThreadRunSubmitToolOutputsParamsToolOutput struct {
945type BetaThreadRunSubmitToolOutputsParamsToolOutput struct {
982 // The output of the tool call to be submitted to continue the run.
946 // The output of the tool call to be submitted to continue the run.
@@ -987,12 +951,10 @@ type BetaThreadRunSubmitToolOutputsParamsToolOutput struct {
987 paramObj
951 paramObj
988}
952}
989
953
990−// IsPresent returns true if the field's value is not omitted and not the JSON
991−// "null". To check if this field is omitted, use [param.IsOmitted].
992−func (f BetaThreadRunSubmitToolOutputsParamsToolOutput) IsPresent() bool {
993− return !param.IsOmitted(f) && !f.IsNull()
994−}
995func (r BetaThreadRunSubmitToolOutputsParamsToolOutput) MarshalJSON() (data []byte, err error) {
954func (r BetaThreadRunSubmitToolOutputsParamsToolOutput) MarshalJSON() (data []byte, err error) {
996 type shadow BetaThreadRunSubmitToolOutputsParamsToolOutput
955 type shadow BetaThreadRunSubmitToolOutputsParamsToolOutput
997 return param.MarshalObject(r, (*shadow)(&r))
956 return param.MarshalObject(r, (*shadow)(&r))
998}
957}
958+func (r *BetaThreadRunSubmitToolOutputsParamsToolOutput) UnmarshalJSON(data []byte) error {
959+ return apijson.UnmarshalRoot(data, r)
960+}
vendor/github.com/openai/openai-go/betathreadrunstep.go+270−238
@@ -16,7 +16,7 @@ import (
16 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/option"
17 "github.com/openai/openai-go/packages/pagination"
17 "github.com/openai/openai-go/packages/pagination"
18 "github.com/openai/openai-go/packages/param"
18 "github.com/openai/openai-go/packages/param"
19− "github.com/openai/openai-go/packages/resp"
19+ "github.com/openai/openai-go/packages/respjson"
20 "github.com/openai/openai-go/shared"
20 "github.com/openai/openai-go/shared"
21 "github.com/openai/openai-go/shared/constant"
21 "github.com/openai/openai-go/shared/constant"
22)
22)
@@ -27,6 +27,8 @@ import (
27// Note, unlike clients, this service does not read variables from the environment
27// Note, unlike clients, this service does not read variables from the environment
28// automatically. You should not instantiate this service directly, and instead use
28// automatically. You should not instantiate this service directly, and instead use
29// the [NewBetaThreadRunStepService] method instead.
29// the [NewBetaThreadRunStepService] method instead.
30+//
31+// Deprecated: The Assistants API is deprecated in favor of the Responses API
30type BetaThreadRunStepService struct {
32type BetaThreadRunStepService struct {
31 Options []option.RequestOption
33 Options []option.RequestOption
32}
34}
@@ -41,6 +43,8 @@ func NewBetaThreadRunStepService(opts ...option.RequestOption) (r BetaThreadRunS
41}
43}
42
44
43// Retrieves a run step.
45// Retrieves a run step.
46+//
47+// Deprecated: The Assistants API is deprecated in favor of the Responses API
44func (r *BetaThreadRunStepService) Get(ctx context.Context, threadID string, runID string, stepID string, query BetaThreadRunStepGetParams, opts ...option.RequestOption) (res *RunStep, err error) {
48func (r *BetaThreadRunStepService) Get(ctx context.Context, threadID string, runID string, stepID string, query BetaThreadRunStepGetParams, opts ...option.RequestOption) (res *RunStep, err error) {
45 opts = append(r.Options[:], opts...)
49 opts = append(r.Options[:], opts...)
46 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
50 opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2")}, opts...)
@@ -62,6 +66,8 @@ func (r *BetaThreadRunStepService) Get(ctx context.Context, threadID string, run
62}
66}
63
67
64// Returns a list of run steps belonging to a run.
68// Returns a list of run steps belonging to a run.
69+//
70+// Deprecated: The Assistants API is deprecated in favor of the Responses API
65func (r *BetaThreadRunStepService) List(ctx context.Context, threadID string, runID string, query BetaThreadRunStepListParams, opts ...option.RequestOption) (res *pagination.CursorPage[RunStep], err error) {
71func (r *BetaThreadRunStepService) List(ctx context.Context, threadID string, runID string, query BetaThreadRunStepListParams, opts ...option.RequestOption) (res *pagination.CursorPage[RunStep], err error) {
66 var raw *http.Response
72 var raw *http.Response
67 opts = append(r.Options[:], opts...)
73 opts = append(r.Options[:], opts...)
@@ -88,6 +94,8 @@ func (r *BetaThreadRunStepService) List(ctx context.Context, threadID string, ru
88}
94}
89
95
90// Returns a list of run steps belonging to a run.
96// Returns a list of run steps belonging to a run.
97+//
98+// Deprecated: The Assistants API is deprecated in favor of the Responses API
91func (r *BetaThreadRunStepService) ListAutoPaging(ctx context.Context, threadID string, runID string, query BetaThreadRunStepListParams, opts ...option.RequestOption) *pagination.CursorPageAutoPager[RunStep] {
99func (r *BetaThreadRunStepService) ListAutoPaging(ctx context.Context, threadID string, runID string, query BetaThreadRunStepListParams, opts ...option.RequestOption) *pagination.CursorPageAutoPager[RunStep] {
92 return pagination.NewCursorPageAutoPager(r.List(ctx, threadID, runID, query, opts...))
100 return pagination.NewCursorPageAutoPager(r.List(ctx, threadID, runID, query, opts...))
93}
101}
@@ -100,13 +108,12 @@ type CodeInterpreterLogs struct {
100 Type constant.Logs `json:"type,required"`
108 Type constant.Logs `json:"type,required"`
101 // The text output from the Code Interpreter tool call.
109 // The text output from the Code Interpreter tool call.
102 Logs string `json:"logs"`
110 Logs string `json:"logs"`
103− // Metadata for the response, check the presence of optional fields with the
111+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
104− // [resp.Field.IsPresent] method.
105 JSON struct {
112 JSON struct {
106− Index resp.Field
113+ Index respjson.Field
107− Type resp.Field
114+ Type respjson.Field
108− Logs resp.Field
115+ Logs respjson.Field
109− ExtraFields map[string]resp.Field
116+ ExtraFields map[string]respjson.Field
110 raw string
117 raw string
111 } `json:"-"`
118 } `json:"-"`
112}
119}
@@ -123,13 +130,12 @@ type CodeInterpreterOutputImage struct {
123 // Always `image`.
130 // Always `image`.
124 Type constant.Image `json:"type,required"`
131 Type constant.Image `json:"type,required"`
125 Image CodeInterpreterOutputImageImage `json:"image"`
132 Image CodeInterpreterOutputImageImage `json:"image"`
126− // Metadata for the response, check the presence of optional fields with the
133+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
127− // [resp.Field.IsPresent] method.
128 JSON struct {
134 JSON struct {
129− Index resp.Field
135+ Index respjson.Field
130− Type resp.Field
136+ Type respjson.Field
131− Image resp.Field
137+ Image respjson.Field
132− ExtraFields map[string]resp.Field
138+ ExtraFields map[string]respjson.Field
133 raw string
139 raw string
134 } `json:"-"`
140 } `json:"-"`
135}
141}
@@ -144,11 +150,10 @@ type CodeInterpreterOutputImageImage struct {
144 // The [file](https://platform.openai.com/docs/api-reference/files) ID of the
150 // The [file](https://platform.openai.com/docs/api-reference/files) ID of the
145 // image.
151 // image.
146 FileID string `json:"file_id"`
152 FileID string `json:"file_id"`
147− // Metadata for the response, check the presence of optional fields with the
153+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
148− // [resp.Field.IsPresent] method.
149 JSON struct {
154 JSON struct {
150− FileID resp.Field
155+ FileID respjson.Field
151− ExtraFields map[string]resp.Field
156+ ExtraFields map[string]respjson.Field
152 raw string
157 raw string
153 } `json:"-"`
158 } `json:"-"`
154}
159}
@@ -168,13 +173,12 @@ type CodeInterpreterToolCall struct {
168 // The type of tool call. This is always going to be `code_interpreter` for this
173 // The type of tool call. This is always going to be `code_interpreter` for this
169 // type of tool call.
174 // type of tool call.
170 Type constant.CodeInterpreter `json:"type,required"`
175 Type constant.CodeInterpreter `json:"type,required"`
171− // Metadata for the response, check the presence of optional fields with the
176+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
172− // [resp.Field.IsPresent] method.
173 JSON struct {
177 JSON struct {
174− ID resp.Field
178+ ID respjson.Field
175− CodeInterpreter resp.Field
179+ CodeInterpreter respjson.Field
176− Type resp.Field
180+ Type respjson.Field
177− ExtraFields map[string]resp.Field
181+ ExtraFields map[string]respjson.Field
178 raw string
182 raw string
179 } `json:"-"`
183 } `json:"-"`
180}
184}
@@ -193,12 +197,11 @@ type CodeInterpreterToolCallCodeInterpreter struct {
193 // or more items, including text (`logs`) or images (`image`). Each of these are
197 // or more items, including text (`logs`) or images (`image`). Each of these are
194 // represented by a different object type.
198 // represented by a different object type.
195 Outputs []CodeInterpreterToolCallCodeInterpreterOutputUnion `json:"outputs,required"`
199 Outputs []CodeInterpreterToolCallCodeInterpreterOutputUnion `json:"outputs,required"`
196− // Metadata for the response, check the presence of optional fields with the
200+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
197− // [resp.Field.IsPresent] method.
198 JSON struct {
201 JSON struct {
199− Input resp.Field
202+ Input respjson.Field
200− Outputs resp.Field
203+ Outputs respjson.Field
201− ExtraFields map[string]resp.Field
204+ ExtraFields map[string]respjson.Field
202 raw string
205 raw string
203 } `json:"-"`
206 } `json:"-"`
204}
207}
@@ -225,22 +228,34 @@ type CodeInterpreterToolCallCodeInterpreterOutputUnion struct {
225 // This field is from variant [CodeInterpreterToolCallCodeInterpreterOutputImage].
228 // This field is from variant [CodeInterpreterToolCallCodeInterpreterOutputImage].
226 Image CodeInterpreterToolCallCodeInterpreterOutputImageImage `json:"image"`
229 Image CodeInterpreterToolCallCodeInterpreterOutputImageImage `json:"image"`
227 JSON struct {
230 JSON struct {
228− Logs resp.Field
231+ Logs respjson.Field
229− Type resp.Field
232+ Type respjson.Field
230− Image resp.Field
233+ Image respjson.Field
231 raw string
234 raw string
232 } `json:"-"`
235 } `json:"-"`
233}
236}
234
237
238+// anyCodeInterpreterToolCallCodeInterpreterOutput is implemented by each variant
239+// of [CodeInterpreterToolCallCodeInterpreterOutputUnion] to add type safety for
240+// the return type of [CodeInterpreterToolCallCodeInterpreterOutputUnion.AsAny]
241+type anyCodeInterpreterToolCallCodeInterpreterOutput interface {
242+ implCodeInterpreterToolCallCodeInterpreterOutputUnion()
243+}
244+
245+func (CodeInterpreterToolCallCodeInterpreterOutputLogs) implCodeInterpreterToolCallCodeInterpreterOutputUnion() {
246+}
247+func (CodeInterpreterToolCallCodeInterpreterOutputImage) implCodeInterpreterToolCallCodeInterpreterOutputUnion() {
248+}
249+
235// Use the following switch statement to find the correct variant
250// Use the following switch statement to find the correct variant
236//
251//
237// switch variant := CodeInterpreterToolCallCodeInterpreterOutputUnion.AsAny().(type) {
252// switch variant := CodeInterpreterToolCallCodeInterpreterOutputUnion.AsAny().(type) {
238−// case CodeInterpreterToolCallCodeInterpreterOutputLogs:
253+// case openai.CodeInterpreterToolCallCodeInterpreterOutputLogs:
239−// case CodeInterpreterToolCallCodeInterpreterOutputImage:
254+// case openai.CodeInterpreterToolCallCodeInterpreterOutputImage:
240// default:
255// default:
241// fmt.Errorf("no variant present")
256// fmt.Errorf("no variant present")
242// }
257// }
243−func (u CodeInterpreterToolCallCodeInterpreterOutputUnion) AsAny() any {
258+func (u CodeInterpreterToolCallCodeInterpreterOutputUnion) AsAny() anyCodeInterpreterToolCallCodeInterpreterOutput {
244 switch u.Type {
259 switch u.Type {
245 case "logs":
260 case "logs":
246 return u.AsLogs()
261 return u.AsLogs()
@@ -273,12 +288,11 @@ type CodeInterpreterToolCallCodeInterpreterOutputLogs struct {
273 Logs string `json:"logs,required"`
288 Logs string `json:"logs,required"`
274 // Always `logs`.
289 // Always `logs`.
275 Type constant.Logs `json:"type,required"`
290 Type constant.Logs `json:"type,required"`
276− // Metadata for the response, check the presence of optional fields with the
291+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
277− // [resp.Field.IsPresent] method.
278 JSON struct {
292 JSON struct {
279− Logs resp.Field
293+ Logs respjson.Field
280− Type resp.Field
294+ Type respjson.Field
281− ExtraFields map[string]resp.Field
295+ ExtraFields map[string]respjson.Field
282 raw string
296 raw string
283 } `json:"-"`
297 } `json:"-"`
284}
298}
@@ -293,12 +307,11 @@ type CodeInterpreterToolCallCodeInterpreterOutputImage struct {
293 Image CodeInterpreterToolCallCodeInterpreterOutputImageImage `json:"image,required"`
307 Image CodeInterpreterToolCallCodeInterpreterOutputImageImage `json:"image,required"`
294 // Always `image`.
308 // Always `image`.
295 Type constant.Image `json:"type,required"`
309 Type constant.Image `json:"type,required"`
296− // Metadata for the response, check the presence of optional fields with the
310+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
297− // [resp.Field.IsPresent] method.
298 JSON struct {
311 JSON struct {
299− Image resp.Field
312+ Image respjson.Field
300− Type resp.Field
313+ Type respjson.Field
301− ExtraFields map[string]resp.Field
314+ ExtraFields map[string]respjson.Field
302 raw string
315 raw string
303 } `json:"-"`
316 } `json:"-"`
304}
317}
@@ -313,11 +326,10 @@ type CodeInterpreterToolCallCodeInterpreterOutputImageImage struct {
313 // The [file](https://platform.openai.com/docs/api-reference/files) ID of the
326 // The [file](https://platform.openai.com/docs/api-reference/files) ID of the
314 // image.
327 // image.
315 FileID string `json:"file_id,required"`
328 FileID string `json:"file_id,required"`
316− // Metadata for the response, check the presence of optional fields with the
329+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
317− // [resp.Field.IsPresent] method.
318 JSON struct {
330 JSON struct {
319− FileID resp.Field
331+ FileID respjson.Field
320− ExtraFields map[string]resp.Field
332+ ExtraFields map[string]respjson.Field
321 raw string
333 raw string
322 } `json:"-"`
334 } `json:"-"`
323}
335}
@@ -339,14 +351,13 @@ type CodeInterpreterToolCallDelta struct {
339 ID string `json:"id"`
351 ID string `json:"id"`
340 // The Code Interpreter tool call definition.
352 // The Code Interpreter tool call definition.
341 CodeInterpreter CodeInterpreterToolCallDeltaCodeInterpreter `json:"code_interpreter"`
353 CodeInterpreter CodeInterpreterToolCallDeltaCodeInterpreter `json:"code_interpreter"`
342− // Metadata for the response, check the presence of optional fields with the
354+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
343− // [resp.Field.IsPresent] method.
344 JSON struct {
355 JSON struct {
345− Index resp.Field
356+ Index respjson.Field
346− Type resp.Field
357+ Type respjson.Field
347− ID resp.Field
358+ ID respjson.Field
348− CodeInterpreter resp.Field
359+ CodeInterpreter respjson.Field
349− ExtraFields map[string]resp.Field
360+ ExtraFields map[string]respjson.Field
350 raw string
361 raw string
351 } `json:"-"`
362 } `json:"-"`
352}
363}
@@ -365,12 +376,11 @@ type CodeInterpreterToolCallDeltaCodeInterpreter struct {
365 // or more items, including text (`logs`) or images (`image`). Each of these are
376 // or more items, including text (`logs`) or images (`image`). Each of these are
366 // represented by a different object type.
377 // represented by a different object type.
367 Outputs []CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion `json:"outputs"`
378 Outputs []CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion `json:"outputs"`
368− // Metadata for the response, check the presence of optional fields with the
379+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
369− // [resp.Field.IsPresent] method.
370 JSON struct {
380 JSON struct {
371− Input resp.Field
381+ Input respjson.Field
372− Outputs resp.Field
382+ Outputs respjson.Field
373− ExtraFields map[string]resp.Field
383+ ExtraFields map[string]respjson.Field
374 raw string
384 raw string
375 } `json:"-"`
385 } `json:"-"`
376}
386}
@@ -397,23 +407,34 @@ type CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion struct {
397 // This field is from variant [CodeInterpreterOutputImage].
407 // This field is from variant [CodeInterpreterOutputImage].
398 Image CodeInterpreterOutputImageImage `json:"image"`
408 Image CodeInterpreterOutputImageImage `json:"image"`
399 JSON struct {
409 JSON struct {
400− Index resp.Field
410+ Index respjson.Field
401− Type resp.Field
411+ Type respjson.Field
402− Logs resp.Field
412+ Logs respjson.Field
403− Image resp.Field
413+ Image respjson.Field
404 raw string
414 raw string
405 } `json:"-"`
415 } `json:"-"`
406}
416}
407
417
418+// anyCodeInterpreterToolCallDeltaCodeInterpreterOutput is implemented by each
419+// variant of [CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion] to add type
420+// safety for the return type of
421+// [CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion.AsAny]
422+type anyCodeInterpreterToolCallDeltaCodeInterpreterOutput interface {
423+ implCodeInterpreterToolCallDeltaCodeInterpreterOutputUnion()
424+}
425+
426+func (CodeInterpreterLogs) implCodeInterpreterToolCallDeltaCodeInterpreterOutputUnion() {}
427+func (CodeInterpreterOutputImage) implCodeInterpreterToolCallDeltaCodeInterpreterOutputUnion() {}
428+
408// Use the following switch statement to find the correct variant
429// Use the following switch statement to find the correct variant
409//
430//
410// switch variant := CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion.AsAny().(type) {
431// switch variant := CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion.AsAny().(type) {
411−// case CodeInterpreterLogs:
432+// case openai.CodeInterpreterLogs:
412−// case CodeInterpreterOutputImage:
433+// case openai.CodeInterpreterOutputImage:
413// default:
434// default:
414// fmt.Errorf("no variant present")
435// fmt.Errorf("no variant present")
415// }
436// }
416−func (u CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) AsAny() any {
437+func (u CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) AsAny() anyCodeInterpreterToolCallDeltaCodeInterpreterOutput {
417 switch u.Type {
438 switch u.Type {
418 case "logs":
439 case "logs":
419 return u.AsLogs()
440 return u.AsLogs()
@@ -448,13 +469,12 @@ type FileSearchToolCall struct {
448 // The type of tool call. This is always going to be `file_search` for this type of
469 // The type of tool call. This is always going to be `file_search` for this type of
449 // tool call.
470 // tool call.
450 Type constant.FileSearch `json:"type,required"`
471 Type constant.FileSearch `json:"type,required"`
451− // Metadata for the response, check the presence of optional fields with the
472+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
452− // [resp.Field.IsPresent] method.
453 JSON struct {
473 JSON struct {
454− ID resp.Field
474+ ID respjson.Field
455− FileSearch resp.Field
475+ FileSearch respjson.Field
456− Type resp.Field
476+ Type respjson.Field
457− ExtraFields map[string]resp.Field
477+ ExtraFields map[string]respjson.Field
458 raw string
478 raw string
459 } `json:"-"`
479 } `json:"-"`
460}
480}
@@ -471,12 +491,11 @@ type FileSearchToolCallFileSearch struct {
471 RankingOptions FileSearchToolCallFileSearchRankingOptions `json:"ranking_options"`
491 RankingOptions FileSearchToolCallFileSearchRankingOptions `json:"ranking_options"`
472 // The results of the file search.
492 // The results of the file search.
473 Results []FileSearchToolCallFileSearchResult `json:"results"`
493 Results []FileSearchToolCallFileSearchResult `json:"results"`
474− // Metadata for the response, check the presence of optional fields with the
494+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
475− // [resp.Field.IsPresent] method.
476 JSON struct {
495 JSON struct {
477− RankingOptions resp.Field
496+ RankingOptions respjson.Field
478− Results resp.Field
497+ Results respjson.Field
479− ExtraFields map[string]resp.Field
498+ ExtraFields map[string]respjson.Field
480 raw string
499 raw string
481 } `json:"-"`
500 } `json:"-"`
482}
501}
@@ -497,12 +516,11 @@ type FileSearchToolCallFileSearchRankingOptions struct {
497 // The score threshold for the file search. All values must be a floating point
516 // The score threshold for the file search. All values must be a floating point
498 // number between 0 and 1.
517 // number between 0 and 1.
499 ScoreThreshold float64 `json:"score_threshold,required"`
518 ScoreThreshold float64 `json:"score_threshold,required"`
500− // Metadata for the response, check the presence of optional fields with the
519+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
501− // [resp.Field.IsPresent] method.
502 JSON struct {
520 JSON struct {
503− Ranker resp.Field
521+ Ranker respjson.Field
504− ScoreThreshold resp.Field
522+ ScoreThreshold respjson.Field
505− ExtraFields map[string]resp.Field
523+ ExtraFields map[string]respjson.Field
506 raw string
524 raw string
507 } `json:"-"`
525 } `json:"-"`
508}
526}
@@ -525,14 +543,13 @@ type FileSearchToolCallFileSearchResult struct {
525 // The content of the result that was found. The content is only included if
543 // The content of the result that was found. The content is only included if
526 // requested via the include query parameter.
544 // requested via the include query parameter.
527 Content []FileSearchToolCallFileSearchResultContent `json:"content"`
545 Content []FileSearchToolCallFileSearchResultContent `json:"content"`
528− // Metadata for the response, check the presence of optional fields with the
546+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
529− // [resp.Field.IsPresent] method.
530 JSON struct {
547 JSON struct {
531− FileID resp.Field
548+ FileID respjson.Field
532− FileName resp.Field
549+ FileName respjson.Field
533− Score resp.Field
550+ Score respjson.Field
534− Content resp.Field
551+ Content respjson.Field
535− ExtraFields map[string]resp.Field
552+ ExtraFields map[string]respjson.Field
536 raw string
553 raw string
537 } `json:"-"`
554 } `json:"-"`
538}
555}
@@ -550,12 +567,11 @@ type FileSearchToolCallFileSearchResultContent struct {
550 //
567 //
551 // Any of "text".
568 // Any of "text".
552 Type string `json:"type"`
569 Type string `json:"type"`
553− // Metadata for the response, check the presence of optional fields with the
570+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
554− // [resp.Field.IsPresent] method.
555 JSON struct {
571 JSON struct {
556− Text resp.Field
572+ Text respjson.Field
557− Type resp.Field
573+ Type respjson.Field
558− ExtraFields map[string]resp.Field
574+ ExtraFields map[string]respjson.Field
559 raw string
575 raw string
560 } `json:"-"`
576 } `json:"-"`
561}
577}
@@ -568,7 +584,7 @@ func (r *FileSearchToolCallFileSearchResultContent) UnmarshalJSON(data []byte) e
568
584
569type FileSearchToolCallDelta struct {
585type FileSearchToolCallDelta struct {
570 // For now, this is always going to be an empty object.
586 // For now, this is always going to be an empty object.
571− FileSearch interface{} `json:"file_search,required"`
587+ FileSearch any `json:"file_search,required"`
572 // The index of the tool call in the tool calls array.
588 // The index of the tool call in the tool calls array.
573 Index int64 `json:"index,required"`
589 Index int64 `json:"index,required"`
574 // The type of tool call. This is always going to be `file_search` for this type of
590 // The type of tool call. This is always going to be `file_search` for this type of
@@ -576,14 +592,13 @@ type FileSearchToolCallDelta struct {
576 Type constant.FileSearch `json:"type,required"`
592 Type constant.FileSearch `json:"type,required"`
577 // The ID of the tool call object.
593 // The ID of the tool call object.
578 ID string `json:"id"`
594 ID string `json:"id"`
579− // Metadata for the response, check the presence of optional fields with the
595+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
580− // [resp.Field.IsPresent] method.
581 JSON struct {
596 JSON struct {
582− FileSearch resp.Field
597+ FileSearch respjson.Field
583− Index resp.Field
598+ Index respjson.Field
584− Type resp.Field
599+ Type respjson.Field
585− ID resp.Field
600+ ID respjson.Field
586− ExtraFields map[string]resp.Field
601+ ExtraFields map[string]respjson.Field
587 raw string
602 raw string
588 } `json:"-"`
603 } `json:"-"`
589}
604}
@@ -602,13 +617,12 @@ type FunctionToolCall struct {
602 // The type of tool call. This is always going to be `function` for this type of
617 // The type of tool call. This is always going to be `function` for this type of
603 // tool call.
618 // tool call.
604 Type constant.Function `json:"type,required"`
619 Type constant.Function `json:"type,required"`
605− // Metadata for the response, check the presence of optional fields with the
620+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
606− // [resp.Field.IsPresent] method.
607 JSON struct {
621 JSON struct {
608− ID resp.Field
622+ ID respjson.Field
609− Function resp.Field
623+ Function respjson.Field
610− Type resp.Field
624+ Type respjson.Field
611− ExtraFields map[string]resp.Field
625+ ExtraFields map[string]respjson.Field
612 raw string
626 raw string
613 } `json:"-"`
627 } `json:"-"`
614}
628}
@@ -629,13 +643,12 @@ type FunctionToolCallFunction struct {
629 // [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs)
643 // [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs)
630 // yet.
644 // yet.
631 Output string `json:"output,required"`
645 Output string `json:"output,required"`
632− // Metadata for the response, check the presence of optional fields with the
646+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
633− // [resp.Field.IsPresent] method.
634 JSON struct {
647 JSON struct {
635− Arguments resp.Field
648+ Arguments respjson.Field
636− Name resp.Field
649+ Name respjson.Field
637− Output resp.Field
650+ Output respjson.Field
638− ExtraFields map[string]resp.Field
651+ ExtraFields map[string]respjson.Field
639 raw string
652 raw string
640 } `json:"-"`
653 } `json:"-"`
641}
654}
@@ -656,14 +669,13 @@ type FunctionToolCallDelta struct {
656 ID string `json:"id"`
669 ID string `json:"id"`
657 // The definition of the function that was called.
670 // The definition of the function that was called.
658 Function FunctionToolCallDeltaFunction `json:"function"`
671 Function FunctionToolCallDeltaFunction `json:"function"`
659− // Metadata for the response, check the presence of optional fields with the
672+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
660− // [resp.Field.IsPresent] method.
661 JSON struct {
673 JSON struct {
662− Index resp.Field
674+ Index respjson.Field
663− Type resp.Field
675+ Type respjson.Field
664− ID resp.Field
676+ ID respjson.Field
665− Function resp.Field
677+ Function respjson.Field
666− ExtraFields map[string]resp.Field
678+ ExtraFields map[string]respjson.Field
667 raw string
679 raw string
668 } `json:"-"`
680 } `json:"-"`
669}
681}
@@ -684,13 +696,12 @@ type FunctionToolCallDeltaFunction struct {
684 // [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs)
696 // [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs)
685 // yet.
697 // yet.
686 Output string `json:"output,nullable"`
698 Output string `json:"output,nullable"`
687− // Metadata for the response, check the presence of optional fields with the
699+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
688− // [resp.Field.IsPresent] method.
689 JSON struct {
700 JSON struct {
690− Arguments resp.Field
701+ Arguments respjson.Field
691− Name resp.Field
702+ Name respjson.Field
692− Output resp.Field
703+ Output respjson.Field
693− ExtraFields map[string]resp.Field
704+ ExtraFields map[string]respjson.Field
694 raw string
705 raw string
695 } `json:"-"`
706 } `json:"-"`
696}
707}
@@ -706,12 +717,11 @@ type MessageCreationStepDetails struct {
706 MessageCreation MessageCreationStepDetailsMessageCreation `json:"message_creation,required"`
717 MessageCreation MessageCreationStepDetailsMessageCreation `json:"message_creation,required"`
707 // Always `message_creation`.
718 // Always `message_creation`.
708 Type constant.MessageCreation `json:"type,required"`
719 Type constant.MessageCreation `json:"type,required"`
709− // Metadata for the response, check the presence of optional fields with the
720+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
710− // [resp.Field.IsPresent] method.
711 JSON struct {
721 JSON struct {
712− MessageCreation resp.Field
722+ MessageCreation respjson.Field
713− Type resp.Field
723+ Type respjson.Field
714− ExtraFields map[string]resp.Field
724+ ExtraFields map[string]respjson.Field
715 raw string
725 raw string
716 } `json:"-"`
726 } `json:"-"`
717}
727}
@@ -725,11 +735,10 @@ func (r *MessageCreationStepDetails) UnmarshalJSON(data []byte) error {
725type MessageCreationStepDetailsMessageCreation struct {
735type MessageCreationStepDetailsMessageCreation struct {
726 // The ID of the message that was created by this run step.
736 // The ID of the message that was created by this run step.
727 MessageID string `json:"message_id,required"`
737 MessageID string `json:"message_id,required"`
728− // Metadata for the response, check the presence of optional fields with the
738+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
729− // [resp.Field.IsPresent] method.
730 JSON struct {
739 JSON struct {
731− MessageID resp.Field
740+ MessageID respjson.Field
732− ExtraFields map[string]resp.Field
741+ ExtraFields map[string]respjson.Field
733 raw string
742 raw string
734 } `json:"-"`
743 } `json:"-"`
735}
744}
@@ -791,26 +800,25 @@ type RunStep struct {
791 // Usage statistics related to the run step. This value will be `null` while the
800 // Usage statistics related to the run step. This value will be `null` while the
792 // run step's status is `in_progress`.
801 // run step's status is `in_progress`.
793 Usage RunStepUsage `json:"usage,required"`
802 Usage RunStepUsage `json:"usage,required"`
794− // Metadata for the response, check the presence of optional fields with the
803+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
795− // [resp.Field.IsPresent] method.
796 JSON struct {
804 JSON struct {
797− ID resp.Field
805+ ID respjson.Field
798− AssistantID resp.Field
806+ AssistantID respjson.Field
799− CancelledAt resp.Field
807+ CancelledAt respjson.Field
800− CompletedAt resp.Field
808+ CompletedAt respjson.Field
801− CreatedAt resp.Field
809+ CreatedAt respjson.Field
802− ExpiredAt resp.Field
810+ ExpiredAt respjson.Field
803− FailedAt resp.Field
811+ FailedAt respjson.Field
804− LastError resp.Field
812+ LastError respjson.Field
805− Metadata resp.Field
813+ Metadata respjson.Field
806− Object resp.Field
814+ Object respjson.Field
807− RunID resp.Field
815+ RunID respjson.Field
808− Status resp.Field
816+ Status respjson.Field
809− StepDetails resp.Field
817+ StepDetails respjson.Field
810− ThreadID resp.Field
818+ ThreadID respjson.Field
811− Type resp.Field
819+ Type respjson.Field
812− Usage resp.Field
820+ Usage respjson.Field
813− ExtraFields map[string]resp.Field
821+ ExtraFields map[string]respjson.Field
814 raw string
822 raw string
815 } `json:"-"`
823 } `json:"-"`
816}
824}
@@ -830,12 +838,11 @@ type RunStepLastError struct {
830 Code string `json:"code,required"`
838 Code string `json:"code,required"`
831 // A human-readable description of the error.
839 // A human-readable description of the error.
832 Message string `json:"message,required"`
840 Message string `json:"message,required"`
833− // Metadata for the response, check the presence of optional fields with the
841+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
834− // [resp.Field.IsPresent] method.
835 JSON struct {
842 JSON struct {
836− Code resp.Field
843+ Code respjson.Field
837− Message resp.Field
844+ Message respjson.Field
838− ExtraFields map[string]resp.Field
845+ ExtraFields map[string]respjson.Field
839 raw string
846 raw string
840 } `json:"-"`
847 } `json:"-"`
841}
848}
@@ -872,22 +879,32 @@ type RunStepStepDetailsUnion struct {
872 // This field is from variant [ToolCallsStepDetails].
879 // This field is from variant [ToolCallsStepDetails].
873 ToolCalls []ToolCallUnion `json:"tool_calls"`
880 ToolCalls []ToolCallUnion `json:"tool_calls"`
874 JSON struct {
881 JSON struct {
875− MessageCreation resp.Field
882+ MessageCreation respjson.Field
876− Type resp.Field
883+ Type respjson.Field
877− ToolCalls resp.Field
884+ ToolCalls respjson.Field
878 raw string
885 raw string
879 } `json:"-"`
886 } `json:"-"`
880}
887}
881
888
889+// anyRunStepStepDetails is implemented by each variant of
890+// [RunStepStepDetailsUnion] to add type safety for the return type of
891+// [RunStepStepDetailsUnion.AsAny]
892+type anyRunStepStepDetails interface {
893+ implRunStepStepDetailsUnion()
894+}
895+
896+func (MessageCreationStepDetails) implRunStepStepDetailsUnion() {}
897+func (ToolCallsStepDetails) implRunStepStepDetailsUnion() {}
898+
882// Use the following switch statement to find the correct variant
899// Use the following switch statement to find the correct variant
883//
900//
884// switch variant := RunStepStepDetailsUnion.AsAny().(type) {
901// switch variant := RunStepStepDetailsUnion.AsAny().(type) {
885−// case MessageCreationStepDetails:
902+// case openai.MessageCreationStepDetails:
886−// case ToolCallsStepDetails:
903+// case openai.ToolCallsStepDetails:
887// default:
904// default:
888// fmt.Errorf("no variant present")
905// fmt.Errorf("no variant present")
889// }
906// }
890−func (u RunStepStepDetailsUnion) AsAny() any {
907+func (u RunStepStepDetailsUnion) AsAny() anyRunStepStepDetails {
891 switch u.Type {
908 switch u.Type {
892 case "message_creation":
909 case "message_creation":
893 return u.AsMessageCreation()
910 return u.AsMessageCreation()
@@ -931,13 +948,12 @@ type RunStepUsage struct {
931 PromptTokens int64 `json:"prompt_tokens,required"`
948 PromptTokens int64 `json:"prompt_tokens,required"`
932 // Total number of tokens used (prompt + completion).
949 // Total number of tokens used (prompt + completion).
933 TotalTokens int64 `json:"total_tokens,required"`
950 TotalTokens int64 `json:"total_tokens,required"`
934− // Metadata for the response, check the presence of optional fields with the
951+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
935− // [resp.Field.IsPresent] method.
936 JSON struct {
952 JSON struct {
937− CompletionTokens resp.Field
953+ CompletionTokens respjson.Field
938− PromptTokens resp.Field
954+ PromptTokens respjson.Field
939− TotalTokens resp.Field
955+ TotalTokens respjson.Field
940− ExtraFields map[string]resp.Field
956+ ExtraFields map[string]respjson.Field
941 raw string
957 raw string
942 } `json:"-"`
958 } `json:"-"`
943}
959}
@@ -952,11 +968,10 @@ func (r *RunStepUsage) UnmarshalJSON(data []byte) error {
952type RunStepDelta struct {
968type RunStepDelta struct {
953 // The details of the run step.
969 // The details of the run step.
954 StepDetails RunStepDeltaStepDetailsUnion `json:"step_details"`
970 StepDetails RunStepDeltaStepDetailsUnion `json:"step_details"`
955− // Metadata for the response, check the presence of optional fields with the
971+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
956− // [resp.Field.IsPresent] method.
957 JSON struct {
972 JSON struct {
958− StepDetails resp.Field
973+ StepDetails respjson.Field
959− ExtraFields map[string]resp.Field
974+ ExtraFields map[string]respjson.Field
960 raw string
975 raw string
961 } `json:"-"`
976 } `json:"-"`
962}
977}
@@ -981,22 +996,32 @@ type RunStepDeltaStepDetailsUnion struct {
981 // This field is from variant [ToolCallDeltaObject].
996 // This field is from variant [ToolCallDeltaObject].
982 ToolCalls []ToolCallDeltaUnion `json:"tool_calls"`
997 ToolCalls []ToolCallDeltaUnion `json:"tool_calls"`
983 JSON struct {
998 JSON struct {
984− Type resp.Field
999+ Type respjson.Field
985− MessageCreation resp.Field
1000+ MessageCreation respjson.Field
986− ToolCalls resp.Field
1001+ ToolCalls respjson.Field
987 raw string
1002 raw string
988 } `json:"-"`
1003 } `json:"-"`
989}
1004}
990
1005
1006+// anyRunStepDeltaStepDetails is implemented by each variant of
1007+// [RunStepDeltaStepDetailsUnion] to add type safety for the return type of
1008+// [RunStepDeltaStepDetailsUnion.AsAny]
1009+type anyRunStepDeltaStepDetails interface {
1010+ implRunStepDeltaStepDetailsUnion()
1011+}
1012+
1013+func (RunStepDeltaMessageDelta) implRunStepDeltaStepDetailsUnion() {}
1014+func (ToolCallDeltaObject) implRunStepDeltaStepDetailsUnion() {}
1015+
991// Use the following switch statement to find the correct variant
1016// Use the following switch statement to find the correct variant
992//
1017//
993// switch variant := RunStepDeltaStepDetailsUnion.AsAny().(type) {
1018// switch variant := RunStepDeltaStepDetailsUnion.AsAny().(type) {
994−// case RunStepDeltaMessageDelta:
1019+// case openai.RunStepDeltaMessageDelta:
995−// case ToolCallDeltaObject:
1020+// case openai.ToolCallDeltaObject:
996// default:
1021// default:
997// fmt.Errorf("no variant present")
1022// fmt.Errorf("no variant present")
998// }
1023// }
999−func (u RunStepDeltaStepDetailsUnion) AsAny() any {
1024+func (u RunStepDeltaStepDetailsUnion) AsAny() anyRunStepDeltaStepDetails {
1000 switch u.Type {
1025 switch u.Type {
1001 case "message_creation":
1026 case "message_creation":
1002 return u.AsMessageCreation()
1027 return u.AsMessageCreation()
@@ -1032,13 +1057,12 @@ type RunStepDeltaEvent struct {
1032 Delta RunStepDelta `json:"delta,required"`
1057 Delta RunStepDelta `json:"delta,required"`
1033 // The object type, which is always `thread.run.step.delta`.
1058 // The object type, which is always `thread.run.step.delta`.
1034 Object constant.ThreadRunStepDelta `json:"object,required"`
1059 Object constant.ThreadRunStepDelta `json:"object,required"`
1035− // Metadata for the response, check the presence of optional fields with the
1060+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1036− // [resp.Field.IsPresent] method.
1037 JSON struct {
1061 JSON struct {
1038− ID resp.Field
1062+ ID respjson.Field
1039− Delta resp.Field
1063+ Delta respjson.Field
1040− Object resp.Field
1064+ Object respjson.Field
1041− ExtraFields map[string]resp.Field
1065+ ExtraFields map[string]respjson.Field
1042 raw string
1066 raw string
1043 } `json:"-"`
1067 } `json:"-"`
1044}
1068}
@@ -1054,12 +1078,11 @@ type RunStepDeltaMessageDelta struct {
1054 // Always `message_creation`.
1078 // Always `message_creation`.
1055 Type constant.MessageCreation `json:"type,required"`
1079 Type constant.MessageCreation `json:"type,required"`
1056 MessageCreation RunStepDeltaMessageDeltaMessageCreation `json:"message_creation"`
1080 MessageCreation RunStepDeltaMessageDeltaMessageCreation `json:"message_creation"`
1057− // Metadata for the response, check the presence of optional fields with the
1081+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1058− // [resp.Field.IsPresent] method.
1059 JSON struct {
1082 JSON struct {
1060− Type resp.Field
1083+ Type respjson.Field
1061− MessageCreation resp.Field
1084+ MessageCreation respjson.Field
1062− ExtraFields map[string]resp.Field
1085+ ExtraFields map[string]respjson.Field
1063 raw string
1086 raw string
1064 } `json:"-"`
1087 } `json:"-"`
1065}
1088}
@@ -1073,11 +1096,10 @@ func (r *RunStepDeltaMessageDelta) UnmarshalJSON(data []byte) error {
1073type RunStepDeltaMessageDeltaMessageCreation struct {
1096type RunStepDeltaMessageDeltaMessageCreation struct {
1074 // The ID of the message that was created by this run step.
1097 // The ID of the message that was created by this run step.
1075 MessageID string `json:"message_id"`
1098 MessageID string `json:"message_id"`
1076− // Metadata for the response, check the presence of optional fields with the
1099+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1077− // [resp.Field.IsPresent] method.
1078 JSON struct {
1100 JSON struct {
1079− MessageID resp.Field
1101+ MessageID respjson.Field
1080− ExtraFields map[string]resp.Field
1102+ ExtraFields map[string]respjson.Field
1081 raw string
1103 raw string
1082 } `json:"-"`
1104 } `json:"-"`
1083}
1105}
@@ -1111,25 +1133,35 @@ type ToolCallUnion struct {
1111 // This field is from variant [FunctionToolCall].
1133 // This field is from variant [FunctionToolCall].
1112 Function FunctionToolCallFunction `json:"function"`
1134 Function FunctionToolCallFunction `json:"function"`
1113 JSON struct {
1135 JSON struct {
1114− ID resp.Field
1136+ ID respjson.Field
1115− CodeInterpreter resp.Field
1137+ CodeInterpreter respjson.Field
1116− Type resp.Field
1138+ Type respjson.Field
1117− FileSearch resp.Field
1139+ FileSearch respjson.Field
1118− Function resp.Field
1140+ Function respjson.Field
1119 raw string
1141 raw string
1120 } `json:"-"`
1142 } `json:"-"`
1121}
1143}
1122
1144
1145+// anyToolCall is implemented by each variant of [ToolCallUnion] to add type safety
1146+// for the return type of [ToolCallUnion.AsAny]
1147+type anyToolCall interface {
1148+ implToolCallUnion()
1149+}
1150+
1151+func (CodeInterpreterToolCall) implToolCallUnion() {}
1152+func (FileSearchToolCall) implToolCallUnion() {}
1153+func (FunctionToolCall) implToolCallUnion() {}
1154+
1123// Use the following switch statement to find the correct variant
1155// Use the following switch statement to find the correct variant
1124//
1156//
1125// switch variant := ToolCallUnion.AsAny().(type) {
1157// switch variant := ToolCallUnion.AsAny().(type) {
1126−// case CodeInterpreterToolCall:
1158+// case openai.CodeInterpreterToolCall:
1127−// case FileSearchToolCall:
1159+// case openai.FileSearchToolCall:
1128−// case FunctionToolCall:
1160+// case openai.FunctionToolCall:
1129// default:
1161// default:
1130// fmt.Errorf("no variant present")
1162// fmt.Errorf("no variant present")
1131// }
1163// }
1132−func (u ToolCallUnion) AsAny() any {
1164+func (u ToolCallUnion) AsAny() anyToolCall {
1133 switch u.Type {
1165 switch u.Type {
1134 case "code_interpreter":
1166 case "code_interpreter":
1135 return u.AsCodeInterpreter()
1167 return u.AsCodeInterpreter()
@@ -1178,30 +1210,40 @@ type ToolCallDeltaUnion struct {
1178 // This field is from variant [CodeInterpreterToolCallDelta].
1210 // This field is from variant [CodeInterpreterToolCallDelta].
1179 CodeInterpreter CodeInterpreterToolCallDeltaCodeInterpreter `json:"code_interpreter"`
1211 CodeInterpreter CodeInterpreterToolCallDeltaCodeInterpreter `json:"code_interpreter"`
1180 // This field is from variant [FileSearchToolCallDelta].
1212 // This field is from variant [FileSearchToolCallDelta].
1181− FileSearch interface{} `json:"file_search"`
1213+ FileSearch any `json:"file_search"`
1182 // This field is from variant [FunctionToolCallDelta].
1214 // This field is from variant [FunctionToolCallDelta].
1183 Function FunctionToolCallDeltaFunction `json:"function"`
1215 Function FunctionToolCallDeltaFunction `json:"function"`
1184 JSON struct {
1216 JSON struct {
1185− Index resp.Field
1217+ Index respjson.Field
1186− Type resp.Field
1218+ Type respjson.Field
1187− ID resp.Field
1219+ ID respjson.Field
1188− CodeInterpreter resp.Field
1220+ CodeInterpreter respjson.Field
1189− FileSearch resp.Field
1221+ FileSearch respjson.Field
1190− Function resp.Field
1222+ Function respjson.Field
1191 raw string
1223 raw string
1192 } `json:"-"`
1224 } `json:"-"`
1193}
1225}
1194
1226
1227+// anyToolCallDelta is implemented by each variant of [ToolCallDeltaUnion] to add
1228+// type safety for the return type of [ToolCallDeltaUnion.AsAny]
1229+type anyToolCallDelta interface {
1230+ implToolCallDeltaUnion()
1231+}
1232+
1233+func (CodeInterpreterToolCallDelta) implToolCallDeltaUnion() {}
1234+func (FileSearchToolCallDelta) implToolCallDeltaUnion() {}
1235+func (FunctionToolCallDelta) implToolCallDeltaUnion() {}
1236+
1195// Use the following switch statement to find the correct variant
1237// Use the following switch statement to find the correct variant
1196//
1238//
1197// switch variant := ToolCallDeltaUnion.AsAny().(type) {
1239// switch variant := ToolCallDeltaUnion.AsAny().(type) {
1198−// case CodeInterpreterToolCallDelta:
1240+// case openai.CodeInterpreterToolCallDelta:
1199−// case FileSearchToolCallDelta:
1241+// case openai.FileSearchToolCallDelta:
1200−// case FunctionToolCallDelta:
1242+// case openai.FunctionToolCallDelta:
1201// default:
1243// default:
1202// fmt.Errorf("no variant present")
1244// fmt.Errorf("no variant present")
1203// }
1245// }
1204−func (u ToolCallDeltaUnion) AsAny() any {
1246+func (u ToolCallDeltaUnion) AsAny() anyToolCallDelta {
1205 switch u.Type {
1247 switch u.Type {
1206 case "code_interpreter":
1248 case "code_interpreter":
1207 return u.AsCodeInterpreter()
1249 return u.AsCodeInterpreter()
@@ -1243,12 +1285,11 @@ type ToolCallDeltaObject struct {
1243 // with one of three types of tools: `code_interpreter`, `file_search`, or
1285 // with one of three types of tools: `code_interpreter`, `file_search`, or
1244 // `function`.
1286 // `function`.
1245 ToolCalls []ToolCallDeltaUnion `json:"tool_calls"`
1287 ToolCalls []ToolCallDeltaUnion `json:"tool_calls"`
1246− // Metadata for the response, check the presence of optional fields with the
1288+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1247− // [resp.Field.IsPresent] method.
1248 JSON struct {
1289 JSON struct {
1249− Type resp.Field
1290+ Type respjson.Field
1250− ToolCalls resp.Field
1291+ ToolCalls respjson.Field
1251− ExtraFields map[string]resp.Field
1292+ ExtraFields map[string]respjson.Field
1252 raw string
1293 raw string
1253 } `json:"-"`
1294 } `json:"-"`
1254}
1295}
@@ -1267,12 +1308,11 @@ type ToolCallsStepDetails struct {
1267 ToolCalls []ToolCallUnion `json:"tool_calls,required"`
1308 ToolCalls []ToolCallUnion `json:"tool_calls,required"`
1268 // Always `tool_calls`.
1309 // Always `tool_calls`.
1269 Type constant.ToolCalls `json:"type,required"`
1310 Type constant.ToolCalls `json:"type,required"`
1270− // Metadata for the response, check the presence of optional fields with the
1311+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1271− // [resp.Field.IsPresent] method.
1272 JSON struct {
1312 JSON struct {
1273− ToolCalls resp.Field
1313+ ToolCalls respjson.Field
1274− Type resp.Field
1314+ Type respjson.Field
1275− ExtraFields map[string]resp.Field
1315+ ExtraFields map[string]respjson.Field
1276 raw string
1316 raw string
1277 } `json:"-"`
1317 } `json:"-"`
1278}
1318}
@@ -1295,13 +1335,9 @@ type BetaThreadRunStepGetParams struct {
1295 paramObj
1335 paramObj
1296}
1336}
1297
1337
1298−// IsPresent returns true if the field's value is not omitted and not the JSON
1299−// "null". To check if this field is omitted, use [param.IsOmitted].
1300−func (f BetaThreadRunStepGetParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1301−
1302// URLQuery serializes [BetaThreadRunStepGetParams]'s query parameters as
1338// URLQuery serializes [BetaThreadRunStepGetParams]'s query parameters as
1303// `url.Values`.
1339// `url.Values`.
1304−func (r BetaThreadRunStepGetParams) URLQuery() (v url.Values) {
1340+func (r BetaThreadRunStepGetParams) URLQuery() (v url.Values, err error) {
1305 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
1341 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
1306 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
1342 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
1307 NestedFormat: apiquery.NestedQueryFormatBrackets,
1343 NestedFormat: apiquery.NestedQueryFormatBrackets,
@@ -1338,13 +1374,9 @@ type BetaThreadRunStepListParams struct {
1338 paramObj
1374 paramObj
1339}
1375}
1340
1376
1341−// IsPresent returns true if the field's value is not omitted and not the JSON
1342−// "null". To check if this field is omitted, use [param.IsOmitted].
1343−func (f BetaThreadRunStepListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1344−
1345// URLQuery serializes [BetaThreadRunStepListParams]'s query parameters as
1377// URLQuery serializes [BetaThreadRunStepListParams]'s query parameters as
1346// `url.Values`.
1378// `url.Values`.
1347−func (r BetaThreadRunStepListParams) URLQuery() (v url.Values) {
1379+func (r BetaThreadRunStepListParams) URLQuery() (v url.Values, err error) {
1348 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
1380 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
1349 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
1381 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
1350 NestedFormat: apiquery.NestedQueryFormatBrackets,
1382 NestedFormat: apiquery.NestedQueryFormatBrackets,
vendor/github.com/openai/openai-go/chatcompletion.go+457−537
@@ -4,11 +4,11 @@ package openai
4
4
5import (
5import (
6 "context"
6 "context"
7+ "encoding/json"
7 "errors"
8 "errors"
8 "fmt"
9 "fmt"
9 "net/http"
10 "net/http"
10 "net/url"
11 "net/url"
11− "reflect"
12
12
13 "github.com/openai/openai-go/internal/apijson"
13 "github.com/openai/openai-go/internal/apijson"
14 "github.com/openai/openai-go/internal/apiquery"
14 "github.com/openai/openai-go/internal/apiquery"
@@ -16,11 +16,10 @@ import (
16 "github.com/openai/openai-go/option"
16 "github.com/openai/openai-go/option"
17 "github.com/openai/openai-go/packages/pagination"
17 "github.com/openai/openai-go/packages/pagination"
18 "github.com/openai/openai-go/packages/param"
18 "github.com/openai/openai-go/packages/param"
19− "github.com/openai/openai-go/packages/resp"
19+ "github.com/openai/openai-go/packages/respjson"
20 "github.com/openai/openai-go/packages/ssestream"
20 "github.com/openai/openai-go/packages/ssestream"
21 "github.com/openai/openai-go/shared"
21 "github.com/openai/openai-go/shared"
22 "github.com/openai/openai-go/shared/constant"
22 "github.com/openai/openai-go/shared/constant"
23− "github.com/tidwall/gjson"
24)
23)
25
24
26// ChatCompletionService contains methods and other services that help with
25// ChatCompletionService contains methods and other services that help with
@@ -176,9 +175,25 @@ type ChatCompletion struct {
176 Model string `json:"model,required"`
175 Model string `json:"model,required"`
177 // The object type, which is always `chat.completion`.
176 // The object type, which is always `chat.completion`.
178 Object constant.ChatCompletion `json:"object,required"`
177 Object constant.ChatCompletion `json:"object,required"`
179− // The service tier used for processing the request.
178+ // Specifies the processing type used for serving the request.
180 //
179 //
180+ // - If set to 'auto', then the request will be processed with the service tier
181+ // configured in the Project settings. Unless otherwise configured, the Project
182+ // will use 'default'.
183+ // - If set to 'default', then the requset will be processed with the standard
184+ // pricing and performance for the selected model.
185+ // - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or
186+ // 'priority', then the request will be processed with the corresponding service
187+ // tier. [Contact sales](https://openai.com/contact-sales) to learn more about
188+ // Priority processing.
189+ // - When not set, the default behavior is 'auto'.
190+ //
191+ // When the `service_tier` parameter is set, the response body will include the
192+ // `service_tier` value based on the processing mode actually used to serve the
193+ // request. This response value may be different from the value set in the
194+ // parameter.
195+ //
181− // Any of "scale", "default".
196+ // Any of "auto", "default", "flex", "scale", "priority".
182 ServiceTier ChatCompletionServiceTier `json:"service_tier,nullable"`
197 ServiceTier ChatCompletionServiceTier `json:"service_tier,nullable"`
183 // This fingerprint represents the backend configuration that the model runs with.
198 // This fingerprint represents the backend configuration that the model runs with.
184 //
199 //
@@ -187,18 +202,17 @@ type ChatCompletion struct {
187 SystemFingerprint string `json:"system_fingerprint"`
202 SystemFingerprint string `json:"system_fingerprint"`
188 // Usage statistics for the completion request.
203 // Usage statistics for the completion request.
189 Usage CompletionUsage `json:"usage"`
204 Usage CompletionUsage `json:"usage"`
190− // Metadata for the response, check the presence of optional fields with the
205+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
191− // [resp.Field.IsPresent] method.
192 JSON struct {
206 JSON struct {
193− ID resp.Field
207+ ID respjson.Field
194− Choices resp.Field
208+ Choices respjson.Field
195− Created resp.Field
209+ Created respjson.Field
196− Model resp.Field
210+ Model respjson.Field
197− Object resp.Field
211+ Object respjson.Field
198− ServiceTier resp.Field
212+ ServiceTier respjson.Field
199− SystemFingerprint resp.Field
213+ SystemFingerprint respjson.Field
200− Usage resp.Field
214+ Usage respjson.Field
201− ExtraFields map[string]resp.Field
215+ ExtraFields map[string]respjson.Field
202 raw string
216 raw string
203 } `json:"-"`
217 } `json:"-"`
204}
218}
@@ -225,14 +239,13 @@ type ChatCompletionChoice struct {
225 Logprobs ChatCompletionChoiceLogprobs `json:"logprobs,required"`
239 Logprobs ChatCompletionChoiceLogprobs `json:"logprobs,required"`
226 // A chat completion message generated by the model.
240 // A chat completion message generated by the model.
227 Message ChatCompletionMessage `json:"message,required"`
241 Message ChatCompletionMessage `json:"message,required"`
228− // Metadata for the response, check the presence of optional fields with the
242+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
229− // [resp.Field.IsPresent] method.
230 JSON struct {
243 JSON struct {
231− FinishReason resp.Field
244+ FinishReason respjson.Field
232− Index resp.Field
245+ Index respjson.Field
233− Logprobs resp.Field
246+ Logprobs respjson.Field
234− Message resp.Field
247+ Message respjson.Field
235− ExtraFields map[string]resp.Field
248+ ExtraFields map[string]respjson.Field
236 raw string
249 raw string
237 } `json:"-"`
250 } `json:"-"`
238}
251}
@@ -249,12 +262,11 @@ type ChatCompletionChoiceLogprobs struct {
249 Content []ChatCompletionTokenLogprob `json:"content,required"`
262 Content []ChatCompletionTokenLogprob `json:"content,required"`
250 // A list of message refusal tokens with log probability information.
263 // A list of message refusal tokens with log probability information.
251 Refusal []ChatCompletionTokenLogprob `json:"refusal,required"`
264 Refusal []ChatCompletionTokenLogprob `json:"refusal,required"`
252− // Metadata for the response, check the presence of optional fields with the
265+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
253− // [resp.Field.IsPresent] method.
254 JSON struct {
266 JSON struct {
255− Content resp.Field
267+ Content respjson.Field
256− Refusal resp.Field
268+ Refusal respjson.Field
257− ExtraFields map[string]resp.Field
269+ ExtraFields map[string]respjson.Field
258 raw string
270 raw string
259 } `json:"-"`
271 } `json:"-"`
260}
272}
@@ -265,12 +277,31 @@ func (r *ChatCompletionChoiceLogprobs) UnmarshalJSON(data []byte) error {
265 return apijson.UnmarshalRoot(data, r)
277 return apijson.UnmarshalRoot(data, r)
266}
278}
267
279
268−// The service tier used for processing the request.
280+// Specifies the processing type used for serving the request.
281+//
282+// - If set to 'auto', then the request will be processed with the service tier
283+// configured in the Project settings. Unless otherwise configured, the Project
284+// will use 'default'.
285+// - If set to 'default', then the requset will be processed with the standard
286+// pricing and performance for the selected model.
287+// - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or
288+// 'priority', then the request will be processed with the corresponding service
289+// tier. [Contact sales](https://openai.com/contact-sales) to learn more about
290+// Priority processing.
291+// - When not set, the default behavior is 'auto'.
292+//
293+// When the `service_tier` parameter is set, the response body will include the
294+// `service_tier` value based on the processing mode actually used to serve the
295+// request. This response value may be different from the value set in the
296+// parameter.
269type ChatCompletionServiceTier string
297type ChatCompletionServiceTier string
270
298
271const (
299const (
300+ ChatCompletionServiceTierAuto ChatCompletionServiceTier = "auto"
301+ ChatCompletionServiceTierDefault ChatCompletionServiceTier = "default"
302+ ChatCompletionServiceTierFlex ChatCompletionServiceTier = "flex"
272− ChatCompletionServiceTierScale ChatCompletionServiceTier = "scale"
303+ ChatCompletionServiceTierScale ChatCompletionServiceTier = "scale"
273− ChatCompletionServiceTierDefault ChatCompletionServiceTier = "default"
304+ ChatCompletionServiceTierPriority ChatCompletionServiceTier = "priority"
274)
305)
275
306
276// Messages sent by the model in response to user messages.
307// Messages sent by the model in response to user messages.
@@ -302,15 +333,13 @@ type ChatCompletionAssistantMessageParam struct {
302 paramObj
333 paramObj
303}
334}
304
335
305−// IsPresent returns true if the field's value is not omitted and not the JSON
306−// "null". To check if this field is omitted, use [param.IsOmitted].
307−func (f ChatCompletionAssistantMessageParam) IsPresent() bool {
308− return !param.IsOmitted(f) && !f.IsNull()
309−}
310func (r ChatCompletionAssistantMessageParam) MarshalJSON() (data []byte, err error) {
336func (r ChatCompletionAssistantMessageParam) MarshalJSON() (data []byte, err error) {
311 type shadow ChatCompletionAssistantMessageParam
337 type shadow ChatCompletionAssistantMessageParam
312 return param.MarshalObject(r, (*shadow)(&r))
338 return param.MarshalObject(r, (*shadow)(&r))
313}
339}
340+func (r *ChatCompletionAssistantMessageParam) UnmarshalJSON(data []byte) error {
341+ return apijson.UnmarshalRoot(data, r)
342+}
314
343
315// Data about a previous audio response from the model.
344// Data about a previous audio response from the model.
316// [Learn more](https://platform.openai.com/docs/guides/audio).
345// [Learn more](https://platform.openai.com/docs/guides/audio).
@@ -322,15 +351,13 @@ type ChatCompletionAssistantMessageParamAudio struct {
322 paramObj
351 paramObj
323}
352}
324
353
325−// IsPresent returns true if the field's value is not omitted and not the JSON
326−// "null". To check if this field is omitted, use [param.IsOmitted].
327−func (f ChatCompletionAssistantMessageParamAudio) IsPresent() bool {
328− return !param.IsOmitted(f) && !f.IsNull()
329−}
330func (r ChatCompletionAssistantMessageParamAudio) MarshalJSON() (data []byte, err error) {
354func (r ChatCompletionAssistantMessageParamAudio) MarshalJSON() (data []byte, err error) {
331 type shadow ChatCompletionAssistantMessageParamAudio
355 type shadow ChatCompletionAssistantMessageParamAudio
332 return param.MarshalObject(r, (*shadow)(&r))
356 return param.MarshalObject(r, (*shadow)(&r))
333}
357}
358+func (r *ChatCompletionAssistantMessageParamAudio) UnmarshalJSON(data []byte) error {
359+ return apijson.UnmarshalRoot(data, r)
360+}
334
361
335// Only one field can be non-zero.
362// Only one field can be non-zero.
336//
363//
@@ -341,13 +368,11 @@ type ChatCompletionAssistantMessageParamContentUnion struct {
341 paramUnion
368 paramUnion
342}
369}
343
370
344−// IsPresent returns true if the field's value is not omitted and not the JSON
345−// "null". To check if this field is omitted, use [param.IsOmitted].
346−func (u ChatCompletionAssistantMessageParamContentUnion) IsPresent() bool {
347− return !param.IsOmitted(u) && !u.IsNull()
348−}
349func (u ChatCompletionAssistantMessageParamContentUnion) MarshalJSON() ([]byte, error) {
371func (u ChatCompletionAssistantMessageParamContentUnion) MarshalJSON() ([]byte, error) {
372+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
373+}
350− return param.MarshalUnion[ChatCompletionAssistantMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts)
374+func (u *ChatCompletionAssistantMessageParamContentUnion) UnmarshalJSON(data []byte) error {
375+ return apijson.UnmarshalRoot(data, u)
351}
376}
352
377
353func (u *ChatCompletionAssistantMessageParamContentUnion) asAny() any {
378func (u *ChatCompletionAssistantMessageParamContentUnion) asAny() any {
@@ -368,13 +393,11 @@ type ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion struct {
368 paramUnion
393 paramUnion
369}
394}
370
395
371−// IsPresent returns true if the field's value is not omitted and not the JSON
372−// "null". To check if this field is omitted, use [param.IsOmitted].
373−func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) IsPresent() bool {
374− return !param.IsOmitted(u) && !u.IsNull()
375−}
376func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) MarshalJSON() ([]byte, error) {
396func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) MarshalJSON() ([]byte, error) {
397+ return param.MarshalUnion(u, u.OfText, u.OfRefusal)
398+}
377− return param.MarshalUnion[ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion](u.OfText, u.OfRefusal)
399+func (u *ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) UnmarshalJSON(data []byte) error {
400+ return apijson.UnmarshalRoot(data, u)
378}
401}
379
402
380func (u *ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) asAny() any {
403func (u *ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) asAny() any {
@@ -415,16 +438,8 @@ func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) GetTy
415func init() {
438func init() {
416 apijson.RegisterUnion[ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion](
439 apijson.RegisterUnion[ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion](
417 "type",
440 "type",
418− apijson.UnionVariant{
419− TypeFilter: gjson.JSON,
420− Type: reflect.TypeOf(ChatCompletionContentPartTextParam{}),
441+ apijson.Discriminator[ChatCompletionContentPartTextParam]("text"),
421− DiscriminatorValue: "text",
422− },
423− apijson.UnionVariant{
424− TypeFilter: gjson.JSON,
425− Type: reflect.TypeOf(ChatCompletionContentPartRefusalParam{}),
442+ apijson.Discriminator[ChatCompletionContentPartRefusalParam]("refusal"),
426− DiscriminatorValue: "refusal",
427− },
428 )
443 )
429}
444}
430
445
@@ -445,15 +460,13 @@ type ChatCompletionAssistantMessageParamFunctionCall struct {
445 paramObj
460 paramObj
446}
461}
447
462
448−// IsPresent returns true if the field's value is not omitted and not the JSON
449−// "null". To check if this field is omitted, use [param.IsOmitted].
450−func (f ChatCompletionAssistantMessageParamFunctionCall) IsPresent() bool {
451− return !param.IsOmitted(f) && !f.IsNull()
452−}
453func (r ChatCompletionAssistantMessageParamFunctionCall) MarshalJSON() (data []byte, err error) {
463func (r ChatCompletionAssistantMessageParamFunctionCall) MarshalJSON() (data []byte, err error) {
454 type shadow ChatCompletionAssistantMessageParamFunctionCall
464 type shadow ChatCompletionAssistantMessageParamFunctionCall
455 return param.MarshalObject(r, (*shadow)(&r))
465 return param.MarshalObject(r, (*shadow)(&r))
456}
466}
467+func (r *ChatCompletionAssistantMessageParamFunctionCall) UnmarshalJSON(data []byte) error {
468+ return apijson.UnmarshalRoot(data, r)
469+}
457
470
458// If the audio output modality is requested, this object contains data about the
471// If the audio output modality is requested, this object contains data about the
459// audio response from the model.
472// audio response from the model.
@@ -469,14 +482,13 @@ type ChatCompletionAudio struct {
469 ExpiresAt int64 `json:"expires_at,required"`
482 ExpiresAt int64 `json:"expires_at,required"`
470 // Transcript of the audio generated by the model.
483 // Transcript of the audio generated by the model.
471 Transcript string `json:"transcript,required"`
484 Transcript string `json:"transcript,required"`
472− // Metadata for the response, check the presence of optional fields with the
485+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
473− // [resp.Field.IsPresent] method.
474 JSON struct {
486 JSON struct {
475− ID resp.Field
487+ ID respjson.Field
476− Data resp.Field
488+ Data respjson.Field
477− ExpiresAt resp.Field
489+ ExpiresAt respjson.Field
478− Transcript resp.Field
490+ Transcript respjson.Field
479− ExtraFields map[string]resp.Field
491+ ExtraFields map[string]respjson.Field
480 raw string
492 raw string
481 } `json:"-"`
493 } `json:"-"`
482}
494}
@@ -496,23 +508,21 @@ type ChatCompletionAudioParam struct {
496 // Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`,
508 // Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`,
497 // or `pcm16`.
509 // or `pcm16`.
498 //
510 //
499− // Any of "wav", "mp3", "flac", "opus", "pcm16".
511+ // Any of "wav", "aac", "mp3", "flac", "opus", "pcm16".
500 Format ChatCompletionAudioParamFormat `json:"format,omitzero,required"`
512 Format ChatCompletionAudioParamFormat `json:"format,omitzero,required"`
501 // The voice the model uses to respond. Supported voices are `alloy`, `ash`,
513 // The voice the model uses to respond. Supported voices are `alloy`, `ash`,
502− // `ballad`, `coral`, `echo`, `sage`, and `shimmer`.
514+ // `ballad`, `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, and `shimmer`.
503− //
504− // Any of "alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse".
505 Voice ChatCompletionAudioParamVoice `json:"voice,omitzero,required"`
515 Voice ChatCompletionAudioParamVoice `json:"voice,omitzero,required"`
506 paramObj
516 paramObj
507}
517}
508
518
509−// IsPresent returns true if the field's value is not omitted and not the JSON
510−// "null". To check if this field is omitted, use [param.IsOmitted].
511−func (f ChatCompletionAudioParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
512func (r ChatCompletionAudioParam) MarshalJSON() (data []byte, err error) {
519func (r ChatCompletionAudioParam) MarshalJSON() (data []byte, err error) {
513 type shadow ChatCompletionAudioParam
520 type shadow ChatCompletionAudioParam
514 return param.MarshalObject(r, (*shadow)(&r))
521 return param.MarshalObject(r, (*shadow)(&r))
515}
522}
523+func (r *ChatCompletionAudioParam) UnmarshalJSON(data []byte) error {
524+ return apijson.UnmarshalRoot(data, r)
525+}
516
526
517// Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`,
527// Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`,
518// or `pcm16`.
528// or `pcm16`.
@@ -520,6 +530,7 @@ type ChatCompletionAudioParamFormat string
520
530
521const (
531const (
522 ChatCompletionAudioParamFormatWAV ChatCompletionAudioParamFormat = "wav"
532 ChatCompletionAudioParamFormatWAV ChatCompletionAudioParamFormat = "wav"
533+ ChatCompletionAudioParamFormatAAC ChatCompletionAudioParamFormat = "aac"
523 ChatCompletionAudioParamFormatMP3 ChatCompletionAudioParamFormat = "mp3"
534 ChatCompletionAudioParamFormatMP3 ChatCompletionAudioParamFormat = "mp3"
524 ChatCompletionAudioParamFormatFLAC ChatCompletionAudioParamFormat = "flac"
535 ChatCompletionAudioParamFormatFLAC ChatCompletionAudioParamFormat = "flac"
525 ChatCompletionAudioParamFormatOpus ChatCompletionAudioParamFormat = "opus"
536 ChatCompletionAudioParamFormatOpus ChatCompletionAudioParamFormat = "opus"
@@ -527,7 +538,7 @@ const (
527)
538)
528
539
529// The voice the model uses to respond. Supported voices are `alloy`, `ash`,
540// The voice the model uses to respond. Supported voices are `alloy`, `ash`,
530−// `ballad`, `coral`, `echo`, `sage`, and `shimmer`.
541+// `ballad`, `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, and `shimmer`.
531type ChatCompletionAudioParamVoice string
542type ChatCompletionAudioParamVoice string
532
543
533const (
544const (
@@ -536,6 +547,9 @@ const (
536 ChatCompletionAudioParamVoiceBallad ChatCompletionAudioParamVoice = "ballad"
547 ChatCompletionAudioParamVoiceBallad ChatCompletionAudioParamVoice = "ballad"
537 ChatCompletionAudioParamVoiceCoral ChatCompletionAudioParamVoice = "coral"
548 ChatCompletionAudioParamVoiceCoral ChatCompletionAudioParamVoice = "coral"
538 ChatCompletionAudioParamVoiceEcho ChatCompletionAudioParamVoice = "echo"
549 ChatCompletionAudioParamVoiceEcho ChatCompletionAudioParamVoice = "echo"
550+ ChatCompletionAudioParamVoiceFable ChatCompletionAudioParamVoice = "fable"
551+ ChatCompletionAudioParamVoiceOnyx ChatCompletionAudioParamVoice = "onyx"
552+ ChatCompletionAudioParamVoiceNova ChatCompletionAudioParamVoice = "nova"
539 ChatCompletionAudioParamVoiceSage ChatCompletionAudioParamVoice = "sage"
553 ChatCompletionAudioParamVoiceSage ChatCompletionAudioParamVoice = "sage"
540 ChatCompletionAudioParamVoiceShimmer ChatCompletionAudioParamVoice = "shimmer"
554 ChatCompletionAudioParamVoiceShimmer ChatCompletionAudioParamVoice = "shimmer"
541 ChatCompletionAudioParamVoiceVerse ChatCompletionAudioParamVoice = "verse"
555 ChatCompletionAudioParamVoiceVerse ChatCompletionAudioParamVoice = "verse"
@@ -558,9 +572,25 @@ type ChatCompletionChunk struct {
558 Model string `json:"model,required"`
572 Model string `json:"model,required"`
559 // The object type, which is always `chat.completion.chunk`.
573 // The object type, which is always `chat.completion.chunk`.
560 Object constant.ChatCompletionChunk `json:"object,required"`
574 Object constant.ChatCompletionChunk `json:"object,required"`
561− // The service tier used for processing the request.
575+ // Specifies the processing type used for serving the request.
576+ //
577+ // - If set to 'auto', then the request will be processed with the service tier
578+ // configured in the Project settings. Unless otherwise configured, the Project
579+ // will use 'default'.
580+ // - If set to 'default', then the requset will be processed with the standard
581+ // pricing and performance for the selected model.
582+ // - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or
583+ // 'priority', then the request will be processed with the corresponding service
584+ // tier. [Contact sales](https://openai.com/contact-sales) to learn more about
585+ // Priority processing.
586+ // - When not set, the default behavior is 'auto'.
587+ //
588+ // When the `service_tier` parameter is set, the response body will include the
589+ // `service_tier` value based on the processing mode actually used to serve the
590+ // request. This response value may be different from the value set in the
591+ // parameter.
562 //
592 //
563− // Any of "scale", "default".
593+ // Any of "auto", "default", "flex", "scale", "priority".
564 ServiceTier ChatCompletionChunkServiceTier `json:"service_tier,nullable"`
594 ServiceTier ChatCompletionChunkServiceTier `json:"service_tier,nullable"`
565 // This fingerprint represents the backend configuration that the model runs with.
595 // This fingerprint represents the backend configuration that the model runs with.
566 // Can be used in conjunction with the `seed` request parameter to understand when
596 // Can be used in conjunction with the `seed` request parameter to understand when
@@ -574,18 +604,17 @@ type ChatCompletionChunk struct {
574 // **NOTE:** If the stream is interrupted or cancelled, you may not receive the
604 // **NOTE:** If the stream is interrupted or cancelled, you may not receive the
575 // final usage chunk which contains the total token usage for the request.
605 // final usage chunk which contains the total token usage for the request.
576 Usage CompletionUsage `json:"usage,nullable"`
606 Usage CompletionUsage `json:"usage,nullable"`
577− // Metadata for the response, check the presence of optional fields with the
607+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
578− // [resp.Field.IsPresent] method.
579 JSON struct {
608 JSON struct {
580− ID resp.Field
609+ ID respjson.Field
581− Choices resp.Field
610+ Choices respjson.Field
582− Created resp.Field
611+ Created respjson.Field
583− Model resp.Field
612+ Model respjson.Field
584− Object resp.Field
613+ Object respjson.Field
585− ServiceTier resp.Field
614+ ServiceTier respjson.Field
586− SystemFingerprint resp.Field
615+ SystemFingerprint respjson.Field
587− Usage resp.Field
616+ Usage respjson.Field
588− ExtraFields map[string]resp.Field
617+ ExtraFields map[string]respjson.Field
589 raw string
618 raw string
590 } `json:"-"`
619 } `json:"-"`
591}
620}
@@ -612,14 +641,13 @@ type ChatCompletionChunkChoice struct {
612 Index int64 `json:"index,required"`
641 Index int64 `json:"index,required"`
613 // Log probability information for the choice.
642 // Log probability information for the choice.
614 Logprobs ChatCompletionChunkChoiceLogprobs `json:"logprobs,nullable"`
643 Logprobs ChatCompletionChunkChoiceLogprobs `json:"logprobs,nullable"`
615− // Metadata for the response, check the presence of optional fields with the
644+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
616− // [resp.Field.IsPresent] method.
617 JSON struct {
645 JSON struct {
618− Delta resp.Field
646+ Delta respjson.Field
619− FinishReason resp.Field
647+ FinishReason respjson.Field
620− Index resp.Field
648+ Index respjson.Field
621− Logprobs resp.Field
649+ Logprobs respjson.Field
622− ExtraFields map[string]resp.Field
650+ ExtraFields map[string]respjson.Field
623 raw string
651 raw string
624 } `json:"-"`
652 } `json:"-"`
625}
653}
@@ -646,15 +674,14 @@ type ChatCompletionChunkChoiceDelta struct {
646 // Any of "developer", "system", "user", "assistant", "tool".
674 // Any of "developer", "system", "user", "assistant", "tool".
647 Role string `json:"role"`
675 Role string `json:"role"`
648 ToolCalls []ChatCompletionChunkChoiceDeltaToolCall `json:"tool_calls"`
676 ToolCalls []ChatCompletionChunkChoiceDeltaToolCall `json:"tool_calls"`
649− // Metadata for the response, check the presence of optional fields with the
677+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
650− // [resp.Field.IsPresent] method.
651 JSON struct {
678 JSON struct {
652− Content resp.Field
679+ Content respjson.Field
653− FunctionCall resp.Field
680+ FunctionCall respjson.Field
654− Refusal resp.Field
681+ Refusal respjson.Field
655− Role resp.Field
682+ Role respjson.Field
656− ToolCalls resp.Field
683+ ToolCalls respjson.Field
657− ExtraFields map[string]resp.Field
684+ ExtraFields map[string]respjson.Field
658 raw string
685 raw string
659 } `json:"-"`
686 } `json:"-"`
660}
687}
@@ -677,12 +704,11 @@ type ChatCompletionChunkChoiceDeltaFunctionCall struct {
677 Arguments string `json:"arguments"`
704 Arguments string `json:"arguments"`
678 // The name of the function to call.
705 // The name of the function to call.
679 Name string `json:"name"`
706 Name string `json:"name"`
680− // Metadata for the response, check the presence of optional fields with the
707+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
681− // [resp.Field.IsPresent] method.
682 JSON struct {
708 JSON struct {
683− Arguments resp.Field
709+ Arguments respjson.Field
684− Name resp.Field
710+ Name respjson.Field
685− ExtraFields map[string]resp.Field
711+ ExtraFields map[string]respjson.Field
686 raw string
712 raw string
687 } `json:"-"`
713 } `json:"-"`
688}
714}
@@ -702,14 +728,13 @@ type ChatCompletionChunkChoiceDeltaToolCall struct {
702 //
728 //
703 // Any of "function".
729 // Any of "function".
704 Type string `json:"type"`
730 Type string `json:"type"`
705− // Metadata for the response, check the presence of optional fields with the
731+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
706− // [resp.Field.IsPresent] method.
707 JSON struct {
732 JSON struct {
708− Index resp.Field
733+ Index respjson.Field
709− ID resp.Field
734+ ID respjson.Field
710− Function resp.Field
735+ Function respjson.Field
711− Type resp.Field
736+ Type respjson.Field
712− ExtraFields map[string]resp.Field
737+ ExtraFields map[string]respjson.Field
713 raw string
738 raw string
714 } `json:"-"`
739 } `json:"-"`
715}
740}
@@ -728,12 +753,11 @@ type ChatCompletionChunkChoiceDeltaToolCallFunction struct {
728 Arguments string `json:"arguments"`
753 Arguments string `json:"arguments"`
729 // The name of the function to call.
754 // The name of the function to call.
730 Name string `json:"name"`
755 Name string `json:"name"`
731− // Metadata for the response, check the presence of optional fields with the
756+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
732− // [resp.Field.IsPresent] method.
733 JSON struct {
757 JSON struct {
734− Arguments resp.Field
758+ Arguments respjson.Field
735− Name resp.Field
759+ Name respjson.Field
736− ExtraFields map[string]resp.Field
760+ ExtraFields map[string]respjson.Field
737 raw string
761 raw string
738 } `json:"-"`
762 } `json:"-"`
739}
763}
@@ -750,12 +774,11 @@ type ChatCompletionChunkChoiceLogprobs struct {
750 Content []ChatCompletionTokenLogprob `json:"content,required"`
774 Content []ChatCompletionTokenLogprob `json:"content,required"`
751 // A list of message refusal tokens with log probability information.
775 // A list of message refusal tokens with log probability information.
752 Refusal []ChatCompletionTokenLogprob `json:"refusal,required"`
776 Refusal []ChatCompletionTokenLogprob `json:"refusal,required"`
753− // Metadata for the response, check the presence of optional fields with the
777+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
754− // [resp.Field.IsPresent] method.
755 JSON struct {
778 JSON struct {
756− Content resp.Field
779+ Content respjson.Field
757− Refusal resp.Field
780+ Refusal respjson.Field
758− ExtraFields map[string]resp.Field
781+ ExtraFields map[string]respjson.Field
759 raw string
782 raw string
760 } `json:"-"`
783 } `json:"-"`
761}
784}
@@ -766,12 +789,31 @@ func (r *ChatCompletionChunkChoiceLogprobs) UnmarshalJSON(data []byte) error {
766 return apijson.UnmarshalRoot(data, r)
789 return apijson.UnmarshalRoot(data, r)
767}
790}
768
791
769−// The service tier used for processing the request.
792+// Specifies the processing type used for serving the request.
793+//
794+// - If set to 'auto', then the request will be processed with the service tier
795+// configured in the Project settings. Unless otherwise configured, the Project
796+// will use 'default'.
797+// - If set to 'default', then the requset will be processed with the standard
798+// pricing and performance for the selected model.
799+// - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or
800+// 'priority', then the request will be processed with the corresponding service
801+// tier. [Contact sales](https://openai.com/contact-sales) to learn more about
802+// Priority processing.
803+// - When not set, the default behavior is 'auto'.
804+//
805+// When the `service_tier` parameter is set, the response body will include the
806+// `service_tier` value based on the processing mode actually used to serve the
807+// request. This response value may be different from the value set in the
808+// parameter.
770type ChatCompletionChunkServiceTier string
809type ChatCompletionChunkServiceTier string
771
810
772const (
811const (
812+ ChatCompletionChunkServiceTierAuto ChatCompletionChunkServiceTier = "auto"
813+ ChatCompletionChunkServiceTierDefault ChatCompletionChunkServiceTier = "default"
814+ ChatCompletionChunkServiceTierFlex ChatCompletionChunkServiceTier = "flex"
773− ChatCompletionChunkServiceTierScale ChatCompletionChunkServiceTier = "scale"
815+ ChatCompletionChunkServiceTierScale ChatCompletionChunkServiceTier = "scale"
774− ChatCompletionChunkServiceTierDefault ChatCompletionChunkServiceTier = "default"
816+ ChatCompletionChunkServiceTierPriority ChatCompletionChunkServiceTier = "priority"
775)
817)
776
818
777func TextContentPart(text string) ChatCompletionContentPartUnionParam {
819func TextContentPart(text string) ChatCompletionContentPartUnionParam {
@@ -809,13 +851,11 @@ type ChatCompletionContentPartUnionParam struct {
809 paramUnion
851 paramUnion
810}
852}
811
853
812−// IsPresent returns true if the field's value is not omitted and not the JSON
813−// "null". To check if this field is omitted, use [param.IsOmitted].
814−func (u ChatCompletionContentPartUnionParam) IsPresent() bool {
815− return !param.IsOmitted(u) && !u.IsNull()
816−}
817func (u ChatCompletionContentPartUnionParam) MarshalJSON() ([]byte, error) {
854func (u ChatCompletionContentPartUnionParam) MarshalJSON() ([]byte, error) {
818− return param.MarshalUnion[ChatCompletionContentPartUnionParam](u.OfText, u.OfImageURL, u.OfInputAudio, u.OfFile)
855+ return param.MarshalUnion(u, u.OfText, u.OfImageURL, u.OfInputAudio, u.OfFile)
856+}
857+func (u *ChatCompletionContentPartUnionParam) UnmarshalJSON(data []byte) error {
858+ return apijson.UnmarshalRoot(data, u)
819}
859}
820
860
821func (u *ChatCompletionContentPartUnionParam) asAny() any {
861func (u *ChatCompletionContentPartUnionParam) asAny() any {
@@ -880,26 +920,10 @@ func (u ChatCompletionContentPartUnionParam) GetType() *string {
880func init() {
920func init() {
881 apijson.RegisterUnion[ChatCompletionContentPartUnionParam](
921 apijson.RegisterUnion[ChatCompletionContentPartUnionParam](
882 "type",
922 "type",
883− apijson.UnionVariant{
884− TypeFilter: gjson.JSON,
885− Type: reflect.TypeOf(ChatCompletionContentPartTextParam{}),
923+ apijson.Discriminator[ChatCompletionContentPartTextParam]("text"),
886− DiscriminatorValue: "text",
887− },
888− apijson.UnionVariant{
889− TypeFilter: gjson.JSON,
890− Type: reflect.TypeOf(ChatCompletionContentPartImageParam{}),
924+ apijson.Discriminator[ChatCompletionContentPartImageParam]("image_url"),
891− DiscriminatorValue: "image_url",
892− },
893− apijson.UnionVariant{
894− TypeFilter: gjson.JSON,
895− Type: reflect.TypeOf(ChatCompletionContentPartInputAudioParam{}),
925+ apijson.Discriminator[ChatCompletionContentPartInputAudioParam]("input_audio"),
896− DiscriminatorValue: "input_audio",
897− },
898− apijson.UnionVariant{
899− TypeFilter: gjson.JSON,
900− Type: reflect.TypeOf(ChatCompletionContentPartFileParam{}),
926+ apijson.Discriminator[ChatCompletionContentPartFileParam]("file"),
901− DiscriminatorValue: "file",
902− },
903 )
927 )
904}
928}
905
929
@@ -916,15 +940,13 @@ type ChatCompletionContentPartFileParam struct {
916 paramObj
940 paramObj
917}
941}
918
942
919−// IsPresent returns true if the field's value is not omitted and not the JSON
920−// "null". To check if this field is omitted, use [param.IsOmitted].
921−func (f ChatCompletionContentPartFileParam) IsPresent() bool {
922− return !param.IsOmitted(f) && !f.IsNull()
923−}
924func (r ChatCompletionContentPartFileParam) MarshalJSON() (data []byte, err error) {
943func (r ChatCompletionContentPartFileParam) MarshalJSON() (data []byte, err error) {
925 type shadow ChatCompletionContentPartFileParam
944 type shadow ChatCompletionContentPartFileParam
926 return param.MarshalObject(r, (*shadow)(&r))
945 return param.MarshalObject(r, (*shadow)(&r))
927}
946}
947+func (r *ChatCompletionContentPartFileParam) UnmarshalJSON(data []byte) error {
948+ return apijson.UnmarshalRoot(data, r)
949+}
928
950
929type ChatCompletionContentPartFileFileParam struct {
951type ChatCompletionContentPartFileFileParam struct {
930 // The base64 encoded file data, used when passing the file to the model as a
952 // The base64 encoded file data, used when passing the file to the model as a
@@ -937,15 +959,13 @@ type ChatCompletionContentPartFileFileParam struct {
937 paramObj
959 paramObj
938}
960}
939
961
940−// IsPresent returns true if the field's value is not omitted and not the JSON
941−// "null". To check if this field is omitted, use [param.IsOmitted].
942−func (f ChatCompletionContentPartFileFileParam) IsPresent() bool {
943− return !param.IsOmitted(f) && !f.IsNull()
944−}
945func (r ChatCompletionContentPartFileFileParam) MarshalJSON() (data []byte, err error) {
962func (r ChatCompletionContentPartFileFileParam) MarshalJSON() (data []byte, err error) {
946 type shadow ChatCompletionContentPartFileFileParam
963 type shadow ChatCompletionContentPartFileFileParam
947 return param.MarshalObject(r, (*shadow)(&r))
964 return param.MarshalObject(r, (*shadow)(&r))
948}
965}
966+func (r *ChatCompletionContentPartFileFileParam) UnmarshalJSON(data []byte) error {
967+ return apijson.UnmarshalRoot(data, r)
968+}
949
969
950// Learn about [image inputs](https://platform.openai.com/docs/guides/vision).
970// Learn about [image inputs](https://platform.openai.com/docs/guides/vision).
951//
971//
@@ -959,15 +979,13 @@ type ChatCompletionContentPartImageParam struct {
959 paramObj
979 paramObj
960}
980}
961
981
962−// IsPresent returns true if the field's value is not omitted and not the JSON
963−// "null". To check if this field is omitted, use [param.IsOmitted].
964−func (f ChatCompletionContentPartImageParam) IsPresent() bool {
965− return !param.IsOmitted(f) && !f.IsNull()
966−}
967func (r ChatCompletionContentPartImageParam) MarshalJSON() (data []byte, err error) {
982func (r ChatCompletionContentPartImageParam) MarshalJSON() (data []byte, err error) {
968 type shadow ChatCompletionContentPartImageParam
983 type shadow ChatCompletionContentPartImageParam
969 return param.MarshalObject(r, (*shadow)(&r))
984 return param.MarshalObject(r, (*shadow)(&r))
970}
985}
986+func (r *ChatCompletionContentPartImageParam) UnmarshalJSON(data []byte) error {
987+ return apijson.UnmarshalRoot(data, r)
988+}
971
989
972// The property URL is required.
990// The property URL is required.
973type ChatCompletionContentPartImageImageURLParam struct {
991type ChatCompletionContentPartImageImageURLParam struct {
@@ -981,19 +999,17 @@ type ChatCompletionContentPartImageImageURLParam struct {
981 paramObj
999 paramObj
982}
1000}
983
1001
984−// IsPresent returns true if the field's value is not omitted and not the JSON
985−// "null". To check if this field is omitted, use [param.IsOmitted].
986−func (f ChatCompletionContentPartImageImageURLParam) IsPresent() bool {
987− return !param.IsOmitted(f) && !f.IsNull()
988−}
989func (r ChatCompletionContentPartImageImageURLParam) MarshalJSON() (data []byte, err error) {
1002func (r ChatCompletionContentPartImageImageURLParam) MarshalJSON() (data []byte, err error) {
990 type shadow ChatCompletionContentPartImageImageURLParam
1003 type shadow ChatCompletionContentPartImageImageURLParam
991 return param.MarshalObject(r, (*shadow)(&r))
1004 return param.MarshalObject(r, (*shadow)(&r))
992}
1005}
1006+func (r *ChatCompletionContentPartImageImageURLParam) UnmarshalJSON(data []byte) error {
1007+ return apijson.UnmarshalRoot(data, r)
1008+}
993
1009
994func init() {
1010func init() {
995 apijson.RegisterFieldValidator[ChatCompletionContentPartImageImageURLParam](
1011 apijson.RegisterFieldValidator[ChatCompletionContentPartImageImageURLParam](
996− "Detail", false, "auto", "low", "high",
1012+ "detail", "auto", "low", "high",
997 )
1013 )
998}
1014}
999
1015
@@ -1009,15 +1025,13 @@ type ChatCompletionContentPartInputAudioParam struct {
1009 paramObj
1025 paramObj
1010}
1026}
1011
1027
1012−// IsPresent returns true if the field's value is not omitted and not the JSON
1013−// "null". To check if this field is omitted, use [param.IsOmitted].
1014−func (f ChatCompletionContentPartInputAudioParam) IsPresent() bool {
1015− return !param.IsOmitted(f) && !f.IsNull()
1016−}
1017func (r ChatCompletionContentPartInputAudioParam) MarshalJSON() (data []byte, err error) {
1028func (r ChatCompletionContentPartInputAudioParam) MarshalJSON() (data []byte, err error) {
1018 type shadow ChatCompletionContentPartInputAudioParam
1029 type shadow ChatCompletionContentPartInputAudioParam
1019 return param.MarshalObject(r, (*shadow)(&r))
1030 return param.MarshalObject(r, (*shadow)(&r))
1020}
1031}
1032+func (r *ChatCompletionContentPartInputAudioParam) UnmarshalJSON(data []byte) error {
1033+ return apijson.UnmarshalRoot(data, r)
1034+}
1021
1035
1022// The properties Data, Format are required.
1036// The properties Data, Format are required.
1023type ChatCompletionContentPartInputAudioInputAudioParam struct {
1037type ChatCompletionContentPartInputAudioInputAudioParam struct {
@@ -1030,19 +1044,17 @@ type ChatCompletionContentPartInputAudioInputAudioParam struct {
1030 paramObj
1044 paramObj
1031}
1045}
1032
1046
1033−// IsPresent returns true if the field's value is not omitted and not the JSON
1034−// "null". To check if this field is omitted, use [param.IsOmitted].
1035−func (f ChatCompletionContentPartInputAudioInputAudioParam) IsPresent() bool {
1036− return !param.IsOmitted(f) && !f.IsNull()
1037−}
1038func (r ChatCompletionContentPartInputAudioInputAudioParam) MarshalJSON() (data []byte, err error) {
1047func (r ChatCompletionContentPartInputAudioInputAudioParam) MarshalJSON() (data []byte, err error) {
1039 type shadow ChatCompletionContentPartInputAudioInputAudioParam
1048 type shadow ChatCompletionContentPartInputAudioInputAudioParam
1040 return param.MarshalObject(r, (*shadow)(&r))
1049 return param.MarshalObject(r, (*shadow)(&r))
1041}
1050}
1051+func (r *ChatCompletionContentPartInputAudioInputAudioParam) UnmarshalJSON(data []byte) error {
1052+ return apijson.UnmarshalRoot(data, r)
1053+}
1042
1054
1043func init() {
1055func init() {
1044 apijson.RegisterFieldValidator[ChatCompletionContentPartInputAudioInputAudioParam](
1056 apijson.RegisterFieldValidator[ChatCompletionContentPartInputAudioInputAudioParam](
1045− "Format", false, "wav", "mp3",
1057+ "format", "wav", "mp3",
1046 )
1058 )
1047}
1059}
1048
1060
@@ -1057,15 +1069,13 @@ type ChatCompletionContentPartRefusalParam struct {
1057 paramObj
1069 paramObj
1058}
1070}
1059
1071
1060−// IsPresent returns true if the field's value is not omitted and not the JSON
1061−// "null". To check if this field is omitted, use [param.IsOmitted].
1062−func (f ChatCompletionContentPartRefusalParam) IsPresent() bool {
1063− return !param.IsOmitted(f) && !f.IsNull()
1064−}
1065func (r ChatCompletionContentPartRefusalParam) MarshalJSON() (data []byte, err error) {
1072func (r ChatCompletionContentPartRefusalParam) MarshalJSON() (data []byte, err error) {
1066 type shadow ChatCompletionContentPartRefusalParam
1073 type shadow ChatCompletionContentPartRefusalParam
1067 return param.MarshalObject(r, (*shadow)(&r))
1074 return param.MarshalObject(r, (*shadow)(&r))
1068}
1075}
1076+func (r *ChatCompletionContentPartRefusalParam) UnmarshalJSON(data []byte) error {
1077+ return apijson.UnmarshalRoot(data, r)
1078+}
1069
1079
1070// Learn about
1080// Learn about
1071// [text inputs](https://platform.openai.com/docs/guides/text-generation).
1081// [text inputs](https://platform.openai.com/docs/guides/text-generation).
@@ -1081,15 +1091,13 @@ type ChatCompletionContentPartTextParam struct {
1081 paramObj
1091 paramObj
1082}
1092}
1083
1093
1084−// IsPresent returns true if the field's value is not omitted and not the JSON
1085−// "null". To check if this field is omitted, use [param.IsOmitted].
1086−func (f ChatCompletionContentPartTextParam) IsPresent() bool {
1087− return !param.IsOmitted(f) && !f.IsNull()
1088−}
1089func (r ChatCompletionContentPartTextParam) MarshalJSON() (data []byte, err error) {
1094func (r ChatCompletionContentPartTextParam) MarshalJSON() (data []byte, err error) {
1090 type shadow ChatCompletionContentPartTextParam
1095 type shadow ChatCompletionContentPartTextParam
1091 return param.MarshalObject(r, (*shadow)(&r))
1096 return param.MarshalObject(r, (*shadow)(&r))
1092}
1097}
1098+func (r *ChatCompletionContentPartTextParam) UnmarshalJSON(data []byte) error {
1099+ return apijson.UnmarshalRoot(data, r)
1100+}
1093
1101
1094type ChatCompletionDeleted struct {
1102type ChatCompletionDeleted struct {
1095 // The ID of the chat completion that was deleted.
1103 // The ID of the chat completion that was deleted.
@@ -1098,13 +1106,12 @@ type ChatCompletionDeleted struct {
1098 Deleted bool `json:"deleted,required"`
1106 Deleted bool `json:"deleted,required"`
1099 // The type of object being deleted.
1107 // The type of object being deleted.
1100 Object constant.ChatCompletionDeleted `json:"object,required"`
1108 Object constant.ChatCompletionDeleted `json:"object,required"`
1101− // Metadata for the response, check the presence of optional fields with the
1109+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1102− // [resp.Field.IsPresent] method.
1103 JSON struct {
1110 JSON struct {
1104− ID resp.Field
1111+ ID respjson.Field
1105− Deleted resp.Field
1112+ Deleted respjson.Field
1106− Object resp.Field
1113+ Object respjson.Field
1107− ExtraFields map[string]resp.Field
1114+ ExtraFields map[string]respjson.Field
1108 raw string
1115 raw string
1109 } `json:"-"`
1116 } `json:"-"`
1110}
1117}
@@ -1133,15 +1140,13 @@ type ChatCompletionDeveloperMessageParam struct {
1133 paramObj
1140 paramObj
1134}
1141}
1135
1142
1136−// IsPresent returns true if the field's value is not omitted and not the JSON
1137−// "null". To check if this field is omitted, use [param.IsOmitted].
1138−func (f ChatCompletionDeveloperMessageParam) IsPresent() bool {
1139− return !param.IsOmitted(f) && !f.IsNull()
1140−}
1141func (r ChatCompletionDeveloperMessageParam) MarshalJSON() (data []byte, err error) {
1143func (r ChatCompletionDeveloperMessageParam) MarshalJSON() (data []byte, err error) {
1142 type shadow ChatCompletionDeveloperMessageParam
1144 type shadow ChatCompletionDeveloperMessageParam
1143 return param.MarshalObject(r, (*shadow)(&r))
1145 return param.MarshalObject(r, (*shadow)(&r))
1144}
1146}
1147+func (r *ChatCompletionDeveloperMessageParam) UnmarshalJSON(data []byte) error {
1148+ return apijson.UnmarshalRoot(data, r)
1149+}
1145
1150
1146// Only one field can be non-zero.
1151// Only one field can be non-zero.
1147//
1152//
@@ -1152,13 +1157,11 @@ type ChatCompletionDeveloperMessageParamContentUnion struct {
1152 paramUnion
1157 paramUnion
1153}
1158}
1154
1159
1155−// IsPresent returns true if the field's value is not omitted and not the JSON
1156−// "null". To check if this field is omitted, use [param.IsOmitted].
1157−func (u ChatCompletionDeveloperMessageParamContentUnion) IsPresent() bool {
1158− return !param.IsOmitted(u) && !u.IsNull()
1159−}
1160func (u ChatCompletionDeveloperMessageParamContentUnion) MarshalJSON() ([]byte, error) {
1160func (u ChatCompletionDeveloperMessageParamContentUnion) MarshalJSON() ([]byte, error) {
1161+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
1162+}
1161− return param.MarshalUnion[ChatCompletionDeveloperMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts)
1163+func (u *ChatCompletionDeveloperMessageParamContentUnion) UnmarshalJSON(data []byte) error {
1164+ return apijson.UnmarshalRoot(data, u)
1162}
1165}
1163
1166
1164func (u *ChatCompletionDeveloperMessageParamContentUnion) asAny() any {
1167func (u *ChatCompletionDeveloperMessageParamContentUnion) asAny() any {
@@ -1180,15 +1183,13 @@ type ChatCompletionFunctionCallOptionParam struct {
1180 paramObj
1183 paramObj
1181}
1184}
1182
1185
1183−// IsPresent returns true if the field's value is not omitted and not the JSON
1184−// "null". To check if this field is omitted, use [param.IsOmitted].
1185−func (f ChatCompletionFunctionCallOptionParam) IsPresent() bool {
1186− return !param.IsOmitted(f) && !f.IsNull()
1187−}
1188func (r ChatCompletionFunctionCallOptionParam) MarshalJSON() (data []byte, err error) {
1186func (r ChatCompletionFunctionCallOptionParam) MarshalJSON() (data []byte, err error) {
1189 type shadow ChatCompletionFunctionCallOptionParam
1187 type shadow ChatCompletionFunctionCallOptionParam
1190 return param.MarshalObject(r, (*shadow)(&r))
1188 return param.MarshalObject(r, (*shadow)(&r))
1191}
1189}
1190+func (r *ChatCompletionFunctionCallOptionParam) UnmarshalJSON(data []byte) error {
1191+ return apijson.UnmarshalRoot(data, r)
1192+}
1192
1193
1193// Deprecated: deprecated
1194// Deprecated: deprecated
1194//
1195//
@@ -1205,15 +1206,13 @@ type ChatCompletionFunctionMessageParam struct {
1205 paramObj
1206 paramObj
1206}
1207}
1207
1208
1208−// IsPresent returns true if the field's value is not omitted and not the JSON
1209−// "null". To check if this field is omitted, use [param.IsOmitted].
1210−func (f ChatCompletionFunctionMessageParam) IsPresent() bool {
1211− return !param.IsOmitted(f) && !f.IsNull()
1212−}
1213func (r ChatCompletionFunctionMessageParam) MarshalJSON() (data []byte, err error) {
1209func (r ChatCompletionFunctionMessageParam) MarshalJSON() (data []byte, err error) {
1214 type shadow ChatCompletionFunctionMessageParam
1210 type shadow ChatCompletionFunctionMessageParam
1215 return param.MarshalObject(r, (*shadow)(&r))
1211 return param.MarshalObject(r, (*shadow)(&r))
1216}
1212}
1213+func (r *ChatCompletionFunctionMessageParam) UnmarshalJSON(data []byte) error {
1214+ return apijson.UnmarshalRoot(data, r)
1215+}
1217
1216
1218// A chat completion message generated by the model.
1217// A chat completion message generated by the model.
1219type ChatCompletionMessage struct {
1218type ChatCompletionMessage struct {
@@ -1237,17 +1236,16 @@ type ChatCompletionMessage struct {
1237 FunctionCall ChatCompletionMessageFunctionCall `json:"function_call"`
1236 FunctionCall ChatCompletionMessageFunctionCall `json:"function_call"`
1238 // The tool calls generated by the model, such as function calls.
1237 // The tool calls generated by the model, such as function calls.
1239 ToolCalls []ChatCompletionMessageToolCall `json:"tool_calls"`
1238 ToolCalls []ChatCompletionMessageToolCall `json:"tool_calls"`
1240− // Metadata for the response, check the presence of optional fields with the
1239+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1241− // [resp.Field.IsPresent] method.
1242 JSON struct {
1240 JSON struct {
1243− Content resp.Field
1241+ Content respjson.Field
1244− Refusal resp.Field
1242+ Refusal respjson.Field
1245− Role resp.Field
1243+ Role respjson.Field
1246− Annotations resp.Field
1244+ Annotations respjson.Field
1247− Audio resp.Field
1245+ Audio respjson.Field
1248− FunctionCall resp.Field
1246+ FunctionCall respjson.Field
1249− ToolCalls resp.Field
1247+ ToolCalls respjson.Field
1250− ExtraFields map[string]resp.Field
1248+ ExtraFields map[string]respjson.Field
1251 raw string
1249 raw string
1252 } `json:"-"`
1250 } `json:"-"`
1253}
1251}
@@ -1300,12 +1298,11 @@ type ChatCompletionMessageAnnotation struct {
1300 Type constant.URLCitation `json:"type,required"`
1298 Type constant.URLCitation `json:"type,required"`
1301 // A URL citation when using web search.
1299 // A URL citation when using web search.
1302 URLCitation ChatCompletionMessageAnnotationURLCitation `json:"url_citation,required"`
1300 URLCitation ChatCompletionMessageAnnotationURLCitation `json:"url_citation,required"`
1303− // Metadata for the response, check the presence of optional fields with the
1301+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1304− // [resp.Field.IsPresent] method.
1305 JSON struct {
1302 JSON struct {
1306− Type resp.Field
1303+ Type respjson.Field
1307− URLCitation resp.Field
1304+ URLCitation respjson.Field
1308− ExtraFields map[string]resp.Field
1305+ ExtraFields map[string]respjson.Field
1309 raw string
1306 raw string
1310 } `json:"-"`
1307 } `json:"-"`
1311}
1308}
@@ -1326,14 +1323,13 @@ type ChatCompletionMessageAnnotationURLCitation struct {
1326 Title string `json:"title,required"`
1323 Title string `json:"title,required"`
1327 // The URL of the web resource.
1324 // The URL of the web resource.
1328 URL string `json:"url,required"`
1325 URL string `json:"url,required"`
1329− // Metadata for the response, check the presence of optional fields with the
1326+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1330− // [resp.Field.IsPresent] method.
1331 JSON struct {
1327 JSON struct {
1332− EndIndex resp.Field
1328+ EndIndex respjson.Field
1333− StartIndex resp.Field
1329+ StartIndex respjson.Field
1334− Title resp.Field
1330+ Title respjson.Field
1335− URL resp.Field
1331+ URL respjson.Field
1336− ExtraFields map[string]resp.Field
1332+ ExtraFields map[string]respjson.Field
1337 raw string
1333 raw string
1338 } `json:"-"`
1334 } `json:"-"`
1339}
1335}
@@ -1356,12 +1352,11 @@ type ChatCompletionMessageFunctionCall struct {
1356 Arguments string `json:"arguments,required"`
1352 Arguments string `json:"arguments,required"`
1357 // The name of the function to call.
1353 // The name of the function to call.
1358 Name string `json:"name,required"`
1354 Name string `json:"name,required"`
1359− // Metadata for the response, check the presence of optional fields with the
1355+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1360− // [resp.Field.IsPresent] method.
1361 JSON struct {
1356 JSON struct {
1362− Arguments resp.Field
1357+ Arguments respjson.Field
1363− Name resp.Field
1358+ Name respjson.Field
1364− ExtraFields map[string]resp.Field
1359+ ExtraFields map[string]respjson.Field
1365 raw string
1360 raw string
1366 } `json:"-"`
1361 } `json:"-"`
1367}
1362}
@@ -1448,17 +1443,17 @@ type ChatCompletionMessageParamUnion struct {
1448 paramUnion
1443 paramUnion
1449}
1444}
1450
1445
1451−// IsPresent returns true if the field's value is not omitted and not the JSON
1452−// "null". To check if this field is omitted, use [param.IsOmitted].
1453−func (u ChatCompletionMessageParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
1454func (u ChatCompletionMessageParamUnion) MarshalJSON() ([]byte, error) {
1446func (u ChatCompletionMessageParamUnion) MarshalJSON() ([]byte, error) {
1455− return param.MarshalUnion[ChatCompletionMessageParamUnion](u.OfDeveloper,
1447+ return param.MarshalUnion(u, u.OfDeveloper,
1456 u.OfSystem,
1448 u.OfSystem,
1457 u.OfUser,
1449 u.OfUser,
1458 u.OfAssistant,
1450 u.OfAssistant,
1459 u.OfTool,
1451 u.OfTool,
1460 u.OfFunction)
1452 u.OfFunction)
1461}
1453}
1454+func (u *ChatCompletionMessageParamUnion) UnmarshalJSON(data []byte) error {
1455+ return apijson.UnmarshalRoot(data, u)
1456+}
1462
1457
1463func (u *ChatCompletionMessageParamUnion) asAny() any {
1458func (u *ChatCompletionMessageParamUnion) asAny() any {
1464 if !param.IsOmitted(u.OfDeveloper) {
1459 if !param.IsOmitted(u.OfDeveloper) {
@@ -1495,7 +1490,7 @@ func (u ChatCompletionMessageParamUnion) GetFunctionCall() *ChatCompletionAssist
1495
1490
1496// Returns a pointer to the underlying variant's property, if present.
1491// Returns a pointer to the underlying variant's property, if present.
1497func (u ChatCompletionMessageParamUnion) GetRefusal() *string {
1492func (u ChatCompletionMessageParamUnion) GetRefusal() *string {
1498− if vt := u.OfAssistant; vt != nil && vt.Refusal.IsPresent() {
1493+ if vt := u.OfAssistant; vt != nil && vt.Refusal.Valid() {
1499 return &vt.Refusal.Value
1494 return &vt.Refusal.Value
1500 }
1495 }
1501 return nil
1496 return nil
@@ -1537,13 +1532,13 @@ func (u ChatCompletionMessageParamUnion) GetRole() *string {
1537
1532
1538// Returns a pointer to the underlying variant's property, if present.
1533// Returns a pointer to the underlying variant's property, if present.
1539func (u ChatCompletionMessageParamUnion) GetName() *string {
1534func (u ChatCompletionMessageParamUnion) GetName() *string {
1540− if vt := u.OfDeveloper; vt != nil && vt.Name.IsPresent() {
1535+ if vt := u.OfDeveloper; vt != nil && vt.Name.Valid() {
1541 return &vt.Name.Value
1536 return &vt.Name.Value
1542− } else if vt := u.OfSystem; vt != nil && vt.Name.IsPresent() {
1537+ } else if vt := u.OfSystem; vt != nil && vt.Name.Valid() {
1543 return &vt.Name.Value
1538 return &vt.Name.Value
1544− } else if vt := u.OfUser; vt != nil && vt.Name.IsPresent() {
1539+ } else if vt := u.OfUser; vt != nil && vt.Name.Valid() {
1545 return &vt.Name.Value
1540 return &vt.Name.Value
1546− } else if vt := u.OfAssistant; vt != nil && vt.Name.IsPresent() {
1541+ } else if vt := u.OfAssistant; vt != nil && vt.Name.Valid() {
1547 return &vt.Name.Value
1542 return &vt.Name.Value
1548 } else if vt := u.OfFunction; vt != nil {
1543 } else if vt := u.OfFunction; vt != nil {
1549 return (*string)(&vt.Name)
1544 return (*string)(&vt.Name)
@@ -1556,32 +1551,25 @@ func (u ChatCompletionMessageParamUnion) GetName() *string {
1556// Or use AsAny() to get the underlying value
1551// Or use AsAny() to get the underlying value
1557func (u ChatCompletionMessageParamUnion) GetContent() (res chatCompletionMessageParamUnionContent) {
1552func (u ChatCompletionMessageParamUnion) GetContent() (res chatCompletionMessageParamUnionContent) {
1558 if vt := u.OfDeveloper; vt != nil {
1553 if vt := u.OfDeveloper; vt != nil {
1559− res.ofChatCompletionDeveloperMessageContent = &vt.Content
1554+ res.any = vt.Content.asAny()
1560 } else if vt := u.OfSystem; vt != nil {
1555 } else if vt := u.OfSystem; vt != nil {
1561− res.ofChatCompletionSystemMessageContent = &vt.Content
1556+ res.any = vt.Content.asAny()
1562 } else if vt := u.OfUser; vt != nil {
1557 } else if vt := u.OfUser; vt != nil {
1563− res.ofChatCompletionUserMessageContent = &vt.Content
1558+ res.any = vt.Content.asAny()
1564 } else if vt := u.OfAssistant; vt != nil {
1559 } else if vt := u.OfAssistant; vt != nil {
1565− res.ofChatCompletionAssistantMessageContent = &vt.Content
1560+ res.any = vt.Content.asAny()
1566 } else if vt := u.OfTool; vt != nil {
1561 } else if vt := u.OfTool; vt != nil {
1567− res.ofChatCompletionToolMessageContent = &vt.Content
1562+ res.any = vt.Content.asAny()
1568− } else if vt := u.OfFunction; vt != nil && vt.Content.IsPresent() {
1563+ } else if vt := u.OfFunction; vt != nil && vt.Content.Valid() {
1569− res.ofString = &vt.Content.Value
1564+ res.any = &vt.Content.Value
1570 }
1565 }
1571 return
1566 return
1572}
1567}
1573
1568
1574−// Only one field can be non-zero.
1569+// Can have the runtime types [*string], [_[]ChatCompletionContentPartTextParam],
1575−//
1570+// [_[]ChatCompletionContentPartUnionParam],
1576−// Use [param.IsOmitted] to confirm if a field is set.
1571+// [\*[]ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion]
1577−type chatCompletionMessageParamUnionContent struct {
1572+type chatCompletionMessageParamUnionContent struct{ any }
1578− ofChatCompletionDeveloperMessageContent *ChatCompletionDeveloperMessageParamContentUnion
1579− ofChatCompletionSystemMessageContent *ChatCompletionSystemMessageParamContentUnion
1580− ofChatCompletionUserMessageContent *ChatCompletionUserMessageParamContentUnion
1581− ofChatCompletionAssistantMessageContent *ChatCompletionAssistantMessageParamContentUnion
1582− ofChatCompletionToolMessageContent *ChatCompletionToolMessageParamContentUnion
1583− ofString *string
1584−}
1585
1573
1586// Use the following switch statement to get the type of the union:
1574// Use the following switch statement to get the type of the union:
1587//
1575//
@@ -1593,56 +1581,17 @@ type chatCompletionMessageParamUnionContent struct {
1593// default:
1581// default:
1594// fmt.Errorf("not present")
1582// fmt.Errorf("not present")
1595// }
1583// }
1596−func (u chatCompletionMessageParamUnionContent) AsAny() any {
1584+func (u chatCompletionMessageParamUnionContent) AsAny() any { return u.any }
1597− if !param.IsOmitted(u.ofChatCompletionDeveloperMessageContent) {
1598− return u.ofChatCompletionDeveloperMessageContent.asAny()
1599− } else if !param.IsOmitted(u.ofChatCompletionSystemMessageContent) {
1600− return u.ofChatCompletionSystemMessageContent.asAny()
1601− } else if !param.IsOmitted(u.ofChatCompletionUserMessageContent) {
1602− return u.ofChatCompletionUserMessageContent.asAny()
1603− } else if !param.IsOmitted(u.ofChatCompletionAssistantMessageContent) {
1604− return u.ofChatCompletionAssistantMessageContent.asAny()
1605− } else if !param.IsOmitted(u.ofChatCompletionToolMessageContent) {
1606− return u.ofChatCompletionToolMessageContent.asAny()
1607− } else if !param.IsOmitted(u.ofString) {
1608− return u.ofString
1609− }
1610− return nil
1611−}
1612
1585
1613func init() {
1586func init() {
1614 apijson.RegisterUnion[ChatCompletionMessageParamUnion](
1587 apijson.RegisterUnion[ChatCompletionMessageParamUnion](
1615 "role",
1588 "role",
1616− apijson.UnionVariant{
1617− TypeFilter: gjson.JSON,
1618− Type: reflect.TypeOf(ChatCompletionDeveloperMessageParam{}),
1589+ apijson.Discriminator[ChatCompletionDeveloperMessageParam]("developer"),
1619− DiscriminatorValue: "developer",
1620− },
1621− apijson.UnionVariant{
1622− TypeFilter: gjson.JSON,
1623− Type: reflect.TypeOf(ChatCompletionSystemMessageParam{}),
1590+ apijson.Discriminator[ChatCompletionSystemMessageParam]("system"),
1624− DiscriminatorValue: "system",
1625− },
1626− apijson.UnionVariant{
1627− TypeFilter: gjson.JSON,
1628− Type: reflect.TypeOf(ChatCompletionUserMessageParam{}),
1591+ apijson.Discriminator[ChatCompletionUserMessageParam]("user"),
1629− DiscriminatorValue: "user",
1630− },
1631− apijson.UnionVariant{
1632− TypeFilter: gjson.JSON,
1633− Type: reflect.TypeOf(ChatCompletionAssistantMessageParam{}),
1592+ apijson.Discriminator[ChatCompletionAssistantMessageParam]("assistant"),
1634− DiscriminatorValue: "assistant",
1635− },
1636− apijson.UnionVariant{
1637− TypeFilter: gjson.JSON,
1638− Type: reflect.TypeOf(ChatCompletionToolMessageParam{}),
1593+ apijson.Discriminator[ChatCompletionToolMessageParam]("tool"),
1639− DiscriminatorValue: "tool",
1640− },
1641− apijson.UnionVariant{
1642− TypeFilter: gjson.JSON,
1643− Type: reflect.TypeOf(ChatCompletionFunctionMessageParam{}),
1594+ apijson.Discriminator[ChatCompletionFunctionMessageParam]("function"),
1644− DiscriminatorValue: "function",
1645− },
1646 )
1595 )
1647}
1596}
1648
1597
@@ -1653,13 +1602,12 @@ type ChatCompletionMessageToolCall struct {
1653 Function ChatCompletionMessageToolCallFunction `json:"function,required"`
1602 Function ChatCompletionMessageToolCallFunction `json:"function,required"`
1654 // The type of the tool. Currently, only `function` is supported.
1603 // The type of the tool. Currently, only `function` is supported.
1655 Type constant.Function `json:"type,required"`
1604 Type constant.Function `json:"type,required"`
1656− // Metadata for the response, check the presence of optional fields with the
1605+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1657− // [resp.Field.IsPresent] method.
1658 JSON struct {
1606 JSON struct {
1659− ID resp.Field
1607+ ID respjson.Field
1660− Function resp.Field
1608+ Function respjson.Field
1661− Type resp.Field
1609+ Type respjson.Field
1662− ExtraFields map[string]resp.Field
1610+ ExtraFields map[string]respjson.Field
1663 raw string
1611 raw string
1664 } `json:"-"`
1612 } `json:"-"`
1665}
1613}
@@ -1675,9 +1623,9 @@ func (r *ChatCompletionMessageToolCall) UnmarshalJSON(data []byte) error {
1675//
1623//
1676// Warning: the fields of the param type will not be present. ToParam should only
1624// Warning: the fields of the param type will not be present. ToParam should only
1677// be used at the last possible moment before sending a request. Test for this with
1625// be used at the last possible moment before sending a request. Test for this with
1678−// ChatCompletionMessageToolCallParam.IsOverridden()
1626+// ChatCompletionMessageToolCallParam.Overrides()
1679func (r ChatCompletionMessageToolCall) ToParam() ChatCompletionMessageToolCallParam {
1627func (r ChatCompletionMessageToolCall) ToParam() ChatCompletionMessageToolCallParam {
1680− return param.OverrideObj[ChatCompletionMessageToolCallParam](r.RawJSON())
1628+ return param.Override[ChatCompletionMessageToolCallParam](json.RawMessage(r.RawJSON()))
1681}
1629}
1682
1630
1683// The function that the model called.
1631// The function that the model called.
@@ -1689,12 +1637,11 @@ type ChatCompletionMessageToolCallFunction struct {
1689 Arguments string `json:"arguments,required"`
1637 Arguments string `json:"arguments,required"`
1690 // The name of the function to call.
1638 // The name of the function to call.
1691 Name string `json:"name,required"`
1639 Name string `json:"name,required"`
1692− // Metadata for the response, check the presence of optional fields with the
1640+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1693− // [resp.Field.IsPresent] method.
1694 JSON struct {
1641 JSON struct {
1695− Arguments resp.Field
1642+ Arguments respjson.Field
1696− Name resp.Field
1643+ Name respjson.Field
1697− ExtraFields map[string]resp.Field
1644+ ExtraFields map[string]respjson.Field
1698 raw string
1645 raw string
1699 } `json:"-"`
1646 } `json:"-"`
1700}
1647}
@@ -1718,15 +1665,13 @@ type ChatCompletionMessageToolCallParam struct {
1718 paramObj
1665 paramObj
1719}
1666}
1720
1667
1721−// IsPresent returns true if the field's value is not omitted and not the JSON
1722−// "null". To check if this field is omitted, use [param.IsOmitted].
1723−func (f ChatCompletionMessageToolCallParam) IsPresent() bool {
1724− return !param.IsOmitted(f) && !f.IsNull()
1725−}
1726func (r ChatCompletionMessageToolCallParam) MarshalJSON() (data []byte, err error) {
1668func (r ChatCompletionMessageToolCallParam) MarshalJSON() (data []byte, err error) {
1727 type shadow ChatCompletionMessageToolCallParam
1669 type shadow ChatCompletionMessageToolCallParam
1728 return param.MarshalObject(r, (*shadow)(&r))
1670 return param.MarshalObject(r, (*shadow)(&r))
1729}
1671}
1672+func (r *ChatCompletionMessageToolCallParam) UnmarshalJSON(data []byte) error {
1673+ return apijson.UnmarshalRoot(data, r)
1674+}
1730
1675
1731// The function that the model called.
1676// The function that the model called.
1732//
1677//
@@ -1742,15 +1687,13 @@ type ChatCompletionMessageToolCallFunctionParam struct {
1742 paramObj
1687 paramObj
1743}
1688}
1744
1689
1745−// IsPresent returns true if the field's value is not omitted and not the JSON
1746−// "null". To check if this field is omitted, use [param.IsOmitted].
1747−func (f ChatCompletionMessageToolCallFunctionParam) IsPresent() bool {
1748− return !param.IsOmitted(f) && !f.IsNull()
1749−}
1750func (r ChatCompletionMessageToolCallFunctionParam) MarshalJSON() (data []byte, err error) {
1690func (r ChatCompletionMessageToolCallFunctionParam) MarshalJSON() (data []byte, err error) {
1751 type shadow ChatCompletionMessageToolCallFunctionParam
1691 type shadow ChatCompletionMessageToolCallFunctionParam
1752 return param.MarshalObject(r, (*shadow)(&r))
1692 return param.MarshalObject(r, (*shadow)(&r))
1753}
1693}
1694+func (r *ChatCompletionMessageToolCallFunctionParam) UnmarshalJSON(data []byte) error {
1695+ return apijson.UnmarshalRoot(data, r)
1696+}
1754
1697
1755// Specifies a tool the model should use. Use to force the model to call a specific
1698// Specifies a tool the model should use. Use to force the model to call a specific
1756// function.
1699// function.
@@ -1765,15 +1708,13 @@ type ChatCompletionNamedToolChoiceParam struct {
1765 paramObj
1708 paramObj
1766}
1709}
1767
1710
1768−// IsPresent returns true if the field's value is not omitted and not the JSON
1769−// "null". To check if this field is omitted, use [param.IsOmitted].
1770−func (f ChatCompletionNamedToolChoiceParam) IsPresent() bool {
1771− return !param.IsOmitted(f) && !f.IsNull()
1772−}
1773func (r ChatCompletionNamedToolChoiceParam) MarshalJSON() (data []byte, err error) {
1711func (r ChatCompletionNamedToolChoiceParam) MarshalJSON() (data []byte, err error) {
1774 type shadow ChatCompletionNamedToolChoiceParam
1712 type shadow ChatCompletionNamedToolChoiceParam
1775 return param.MarshalObject(r, (*shadow)(&r))
1713 return param.MarshalObject(r, (*shadow)(&r))
1776}
1714}
1715+func (r *ChatCompletionNamedToolChoiceParam) UnmarshalJSON(data []byte) error {
1716+ return apijson.UnmarshalRoot(data, r)
1717+}
1777
1718
1778// The property Name is required.
1719// The property Name is required.
1779type ChatCompletionNamedToolChoiceFunctionParam struct {
1720type ChatCompletionNamedToolChoiceFunctionParam struct {
@@ -1782,15 +1723,13 @@ type ChatCompletionNamedToolChoiceFunctionParam struct {
1782 paramObj
1723 paramObj
1783}
1724}
1784
1725
1785−// IsPresent returns true if the field's value is not omitted and not the JSON
1786−// "null". To check if this field is omitted, use [param.IsOmitted].
1787−func (f ChatCompletionNamedToolChoiceFunctionParam) IsPresent() bool {
1788− return !param.IsOmitted(f) && !f.IsNull()
1789−}
1790func (r ChatCompletionNamedToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) {
1726func (r ChatCompletionNamedToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) {
1791 type shadow ChatCompletionNamedToolChoiceFunctionParam
1727 type shadow ChatCompletionNamedToolChoiceFunctionParam
1792 return param.MarshalObject(r, (*shadow)(&r))
1728 return param.MarshalObject(r, (*shadow)(&r))
1793}
1729}
1730+func (r *ChatCompletionNamedToolChoiceFunctionParam) UnmarshalJSON(data []byte) error {
1731+ return apijson.UnmarshalRoot(data, r)
1732+}
1794
1733
1795// Static predicted output content, such as the content of a text file that is
1734// Static predicted output content, such as the content of a text file that is
1796// being regenerated.
1735// being regenerated.
@@ -1809,15 +1748,13 @@ type ChatCompletionPredictionContentParam struct {
1809 paramObj
1748 paramObj
1810}
1749}
1811
1750
1812−// IsPresent returns true if the field's value is not omitted and not the JSON
1813−// "null". To check if this field is omitted, use [param.IsOmitted].
1814−func (f ChatCompletionPredictionContentParam) IsPresent() bool {
1815− return !param.IsOmitted(f) && !f.IsNull()
1816−}
1817func (r ChatCompletionPredictionContentParam) MarshalJSON() (data []byte, err error) {
1751func (r ChatCompletionPredictionContentParam) MarshalJSON() (data []byte, err error) {
1818 type shadow ChatCompletionPredictionContentParam
1752 type shadow ChatCompletionPredictionContentParam
1819 return param.MarshalObject(r, (*shadow)(&r))
1753 return param.MarshalObject(r, (*shadow)(&r))
1820}
1754}
1755+func (r *ChatCompletionPredictionContentParam) UnmarshalJSON(data []byte) error {
1756+ return apijson.UnmarshalRoot(data, r)
1757+}
1821
1758
1822// Only one field can be non-zero.
1759// Only one field can be non-zero.
1823//
1760//
@@ -1828,13 +1765,11 @@ type ChatCompletionPredictionContentContentUnionParam struct {
1828 paramUnion
1765 paramUnion
1829}
1766}
1830
1767
1831−// IsPresent returns true if the field's value is not omitted and not the JSON
1832−// "null". To check if this field is omitted, use [param.IsOmitted].
1833−func (u ChatCompletionPredictionContentContentUnionParam) IsPresent() bool {
1834− return !param.IsOmitted(u) && !u.IsNull()
1835−}
1836func (u ChatCompletionPredictionContentContentUnionParam) MarshalJSON() ([]byte, error) {
1768func (u ChatCompletionPredictionContentContentUnionParam) MarshalJSON() ([]byte, error) {
1769+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
1770+}
1837− return param.MarshalUnion[ChatCompletionPredictionContentContentUnionParam](u.OfString, u.OfArrayOfContentParts)
1771+func (u *ChatCompletionPredictionContentContentUnionParam) UnmarshalJSON(data []byte) error {
1772+ return apijson.UnmarshalRoot(data, u)
1838}
1773}
1839
1774
1840func (u *ChatCompletionPredictionContentContentUnionParam) asAny() any {
1775func (u *ChatCompletionPredictionContentContentUnionParam) asAny() any {
@@ -1850,11 +1785,10 @@ func (u *ChatCompletionPredictionContentContentUnionParam) asAny() any {
1850type ChatCompletionStoreMessage struct {
1785type ChatCompletionStoreMessage struct {
1851 // The identifier of the chat message.
1786 // The identifier of the chat message.
1852 ID string `json:"id,required"`
1787 ID string `json:"id,required"`
1853− // Metadata for the response, check the presence of optional fields with the
1788+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1854− // [resp.Field.IsPresent] method.
1855 JSON struct {
1789 JSON struct {
1856− ID resp.Field
1790+ ID respjson.Field
1857− ExtraFields map[string]resp.Field
1791+ ExtraFields map[string]respjson.Field
1858 raw string
1792 raw string
1859 } `json:"-"`
1793 } `json:"-"`
1860 ChatCompletionMessage
1794 ChatCompletionMessage
@@ -1879,13 +1813,13 @@ type ChatCompletionStreamOptionsParam struct {
1879 paramObj
1813 paramObj
1880}
1814}
1881
1815
1882−// IsPresent returns true if the field's value is not omitted and not the JSON
1883−// "null". To check if this field is omitted, use [param.IsOmitted].
1884−func (f ChatCompletionStreamOptionsParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1885func (r ChatCompletionStreamOptionsParam) MarshalJSON() (data []byte, err error) {
1816func (r ChatCompletionStreamOptionsParam) MarshalJSON() (data []byte, err error) {
1886 type shadow ChatCompletionStreamOptionsParam
1817 type shadow ChatCompletionStreamOptionsParam
1887 return param.MarshalObject(r, (*shadow)(&r))
1818 return param.MarshalObject(r, (*shadow)(&r))
1888}
1819}
1820+func (r *ChatCompletionStreamOptionsParam) UnmarshalJSON(data []byte) error {
1821+ return apijson.UnmarshalRoot(data, r)
1822+}
1889
1823
1890// Developer-provided instructions that the model should follow, regardless of
1824// Developer-provided instructions that the model should follow, regardless of
1891// messages sent by the user. With o1 models and newer, use `developer` messages
1825// messages sent by the user. With o1 models and newer, use `developer` messages
@@ -1905,13 +1839,13 @@ type ChatCompletionSystemMessageParam struct {
1905 paramObj
1839 paramObj
1906}
1840}
1907
1841
1908−// IsPresent returns true if the field's value is not omitted and not the JSON
1909−// "null". To check if this field is omitted, use [param.IsOmitted].
1910−func (f ChatCompletionSystemMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
1911func (r ChatCompletionSystemMessageParam) MarshalJSON() (data []byte, err error) {
1842func (r ChatCompletionSystemMessageParam) MarshalJSON() (data []byte, err error) {
1912 type shadow ChatCompletionSystemMessageParam
1843 type shadow ChatCompletionSystemMessageParam
1913 return param.MarshalObject(r, (*shadow)(&r))
1844 return param.MarshalObject(r, (*shadow)(&r))
1914}
1845}
1846+func (r *ChatCompletionSystemMessageParam) UnmarshalJSON(data []byte) error {
1847+ return apijson.UnmarshalRoot(data, r)
1848+}
1915
1849
1916// Only one field can be non-zero.
1850// Only one field can be non-zero.
1917//
1851//
@@ -1922,13 +1856,11 @@ type ChatCompletionSystemMessageParamContentUnion struct {
1922 paramUnion
1856 paramUnion
1923}
1857}
1924
1858
1925−// IsPresent returns true if the field's value is not omitted and not the JSON
1926−// "null". To check if this field is omitted, use [param.IsOmitted].
1927−func (u ChatCompletionSystemMessageParamContentUnion) IsPresent() bool {
1928− return !param.IsOmitted(u) && !u.IsNull()
1929−}
1930func (u ChatCompletionSystemMessageParamContentUnion) MarshalJSON() ([]byte, error) {
1859func (u ChatCompletionSystemMessageParamContentUnion) MarshalJSON() ([]byte, error) {
1860+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
1861+}
1931− return param.MarshalUnion[ChatCompletionSystemMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts)
1862+func (u *ChatCompletionSystemMessageParamContentUnion) UnmarshalJSON(data []byte) error {
1863+ return apijson.UnmarshalRoot(data, u)
1932}
1864}
1933
1865
1934func (u *ChatCompletionSystemMessageParamContentUnion) asAny() any {
1866func (u *ChatCompletionSystemMessageParamContentUnion) asAny() any {
@@ -1956,14 +1888,13 @@ type ChatCompletionTokenLogprob struct {
1956 // position. In rare cases, there may be fewer than the number of requested
1888 // position. In rare cases, there may be fewer than the number of requested
1957 // `top_logprobs` returned.
1889 // `top_logprobs` returned.
1958 TopLogprobs []ChatCompletionTokenLogprobTopLogprob `json:"top_logprobs,required"`
1890 TopLogprobs []ChatCompletionTokenLogprobTopLogprob `json:"top_logprobs,required"`
1959− // Metadata for the response, check the presence of optional fields with the
1891+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1960− // [resp.Field.IsPresent] method.
1961 JSON struct {
1892 JSON struct {
1962− Token resp.Field
1893+ Token respjson.Field
1963− Bytes resp.Field
1894+ Bytes respjson.Field
1964− Logprob resp.Field
1895+ Logprob respjson.Field
1965− TopLogprobs resp.Field
1896+ TopLogprobs respjson.Field
1966− ExtraFields map[string]resp.Field
1897+ ExtraFields map[string]respjson.Field
1967 raw string
1898 raw string
1968 } `json:"-"`
1899 } `json:"-"`
1969}
1900}
@@ -1986,13 +1917,12 @@ type ChatCompletionTokenLogprobTopLogprob struct {
1986 // tokens. Otherwise, the value `-9999.0` is used to signify that the token is very
1917 // tokens. Otherwise, the value `-9999.0` is used to signify that the token is very
1987 // unlikely.
1918 // unlikely.
1988 Logprob float64 `json:"logprob,required"`
1919 Logprob float64 `json:"logprob,required"`
1989− // Metadata for the response, check the presence of optional fields with the
1920+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
1990− // [resp.Field.IsPresent] method.
1991 JSON struct {
1921 JSON struct {
1992− Token resp.Field
1922+ Token respjson.Field
1993− Bytes resp.Field
1923+ Bytes respjson.Field
1994− Logprob resp.Field
1924+ Logprob respjson.Field
1995− ExtraFields map[string]resp.Field
1925+ ExtraFields map[string]respjson.Field
1996 raw string
1926 raw string
1997 } `json:"-"`
1927 } `json:"-"`
1998}
1928}
@@ -2013,13 +1943,13 @@ type ChatCompletionToolParam struct {
2013 paramObj
1943 paramObj
2014}
1944}
2015
1945
2016−// IsPresent returns true if the field's value is not omitted and not the JSON
2017−// "null". To check if this field is omitted, use [param.IsOmitted].
2018−func (f ChatCompletionToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2019func (r ChatCompletionToolParam) MarshalJSON() (data []byte, err error) {
1946func (r ChatCompletionToolParam) MarshalJSON() (data []byte, err error) {
2020 type shadow ChatCompletionToolParam
1947 type shadow ChatCompletionToolParam
2021 return param.MarshalObject(r, (*shadow)(&r))
1948 return param.MarshalObject(r, (*shadow)(&r))
2022}
1949}
1950+func (r *ChatCompletionToolParam) UnmarshalJSON(data []byte) error {
1951+ return apijson.UnmarshalRoot(data, r)
1952+}
2023
1953
2024func ChatCompletionToolChoiceOptionParamOfChatCompletionNamedToolChoice(function ChatCompletionNamedToolChoiceFunctionParam) ChatCompletionToolChoiceOptionUnionParam {
1954func ChatCompletionToolChoiceOptionParamOfChatCompletionNamedToolChoice(function ChatCompletionNamedToolChoiceFunctionParam) ChatCompletionToolChoiceOptionUnionParam {
2025 var variant ChatCompletionNamedToolChoiceParam
1955 var variant ChatCompletionNamedToolChoiceParam
@@ -2037,13 +1967,11 @@ type ChatCompletionToolChoiceOptionUnionParam struct {
2037 paramUnion
1967 paramUnion
2038}
1968}
2039
1969
2040−// IsPresent returns true if the field's value is not omitted and not the JSON
2041−// "null". To check if this field is omitted, use [param.IsOmitted].
2042−func (u ChatCompletionToolChoiceOptionUnionParam) IsPresent() bool {
2043− return !param.IsOmitted(u) && !u.IsNull()
2044−}
2045func (u ChatCompletionToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) {
1970func (u ChatCompletionToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) {
1971+ return param.MarshalUnion(u, u.OfAuto, u.OfChatCompletionNamedToolChoice)
1972+}
2046− return param.MarshalUnion[ChatCompletionToolChoiceOptionUnionParam](u.OfAuto, u.OfChatCompletionNamedToolChoice)
1973+func (u *ChatCompletionToolChoiceOptionUnionParam) UnmarshalJSON(data []byte) error {
1974+ return apijson.UnmarshalRoot(data, u)
2047}
1975}
2048
1976
2049func (u *ChatCompletionToolChoiceOptionUnionParam) asAny() any {
1977func (u *ChatCompletionToolChoiceOptionUnionParam) asAny() any {
@@ -2055,21 +1983,16 @@ func (u *ChatCompletionToolChoiceOptionUnionParam) asAny() any {
2055 return nil
1983 return nil
2056}
1984}
2057
1985
2058−// Returns a pointer to the underlying variant's property, if present.
1986+// `none` means the model will not call any tool and instead generates a message.
2059−func (u ChatCompletionToolChoiceOptionUnionParam) GetFunction() *ChatCompletionNamedToolChoiceFunctionParam {
1987+// `auto` means the model can pick between generating a message or calling one or
2060− if vt := u.OfChatCompletionNamedToolChoice; vt != nil {
1988+// more tools. `required` means the model must call one or more tools.
2061− return &vt.Function
1989+type ChatCompletionToolChoiceOptionAuto string
2062− }
2063− return nil
2064−}
2065
1990
2066−// Returns a pointer to the underlying variant's property, if present.
1991+const (
2067−func (u ChatCompletionToolChoiceOptionUnionParam) GetType() *string {
1992+ ChatCompletionToolChoiceOptionAutoNone ChatCompletionToolChoiceOptionAuto = "none"
2068− if vt := u.OfChatCompletionNamedToolChoice; vt != nil {
1993+ ChatCompletionToolChoiceOptionAutoAuto ChatCompletionToolChoiceOptionAuto = "auto"
2069− return (*string)(&vt.Type)
1994+ ChatCompletionToolChoiceOptionAutoRequired ChatCompletionToolChoiceOptionAuto = "required"
2070− }
1995+)
2071− return nil
2072−}
2073
1996
2074// The properties Content, Role, ToolCallID are required.
1997// The properties Content, Role, ToolCallID are required.
2075type ChatCompletionToolMessageParam struct {
1998type ChatCompletionToolMessageParam struct {
@@ -2084,13 +2007,13 @@ type ChatCompletionToolMessageParam struct {
2084 paramObj
2007 paramObj
2085}
2008}
2086
2009
2087−// IsPresent returns true if the field's value is not omitted and not the JSON
2088−// "null". To check if this field is omitted, use [param.IsOmitted].
2089−func (f ChatCompletionToolMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2090func (r ChatCompletionToolMessageParam) MarshalJSON() (data []byte, err error) {
2010func (r ChatCompletionToolMessageParam) MarshalJSON() (data []byte, err error) {
2091 type shadow ChatCompletionToolMessageParam
2011 type shadow ChatCompletionToolMessageParam
2092 return param.MarshalObject(r, (*shadow)(&r))
2012 return param.MarshalObject(r, (*shadow)(&r))
2093}
2013}
2014+func (r *ChatCompletionToolMessageParam) UnmarshalJSON(data []byte) error {
2015+ return apijson.UnmarshalRoot(data, r)
2016+}
2094
2017
2095// Only one field can be non-zero.
2018// Only one field can be non-zero.
2096//
2019//
@@ -2101,13 +2024,11 @@ type ChatCompletionToolMessageParamContentUnion struct {
2101 paramUnion
2024 paramUnion
2102}
2025}
2103
2026
2104−// IsPresent returns true if the field's value is not omitted and not the JSON
2105−// "null". To check if this field is omitted, use [param.IsOmitted].
2106−func (u ChatCompletionToolMessageParamContentUnion) IsPresent() bool {
2107− return !param.IsOmitted(u) && !u.IsNull()
2108−}
2109func (u ChatCompletionToolMessageParamContentUnion) MarshalJSON() ([]byte, error) {
2027func (u ChatCompletionToolMessageParamContentUnion) MarshalJSON() ([]byte, error) {
2028+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
2029+}
2110− return param.MarshalUnion[ChatCompletionToolMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts)
2030+func (u *ChatCompletionToolMessageParamContentUnion) UnmarshalJSON(data []byte) error {
2031+ return apijson.UnmarshalRoot(data, u)
2111}
2032}
2112
2033
2113func (u *ChatCompletionToolMessageParamContentUnion) asAny() any {
2034func (u *ChatCompletionToolMessageParamContentUnion) asAny() any {
@@ -2136,13 +2057,13 @@ type ChatCompletionUserMessageParam struct {
2136 paramObj
2057 paramObj
2137}
2058}
2138
2059
2139−// IsPresent returns true if the field's value is not omitted and not the JSON
2140−// "null". To check if this field is omitted, use [param.IsOmitted].
2141−func (f ChatCompletionUserMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2142func (r ChatCompletionUserMessageParam) MarshalJSON() (data []byte, err error) {
2060func (r ChatCompletionUserMessageParam) MarshalJSON() (data []byte, err error) {
2143 type shadow ChatCompletionUserMessageParam
2061 type shadow ChatCompletionUserMessageParam
2144 return param.MarshalObject(r, (*shadow)(&r))
2062 return param.MarshalObject(r, (*shadow)(&r))
2145}
2063}
2064+func (r *ChatCompletionUserMessageParam) UnmarshalJSON(data []byte) error {
2065+ return apijson.UnmarshalRoot(data, r)
2066+}
2146
2067
2147// Only one field can be non-zero.
2068// Only one field can be non-zero.
2148//
2069//
@@ -2153,13 +2074,11 @@ type ChatCompletionUserMessageParamContentUnion struct {
2153 paramUnion
2074 paramUnion
2154}
2075}
2155
2076
2156−// IsPresent returns true if the field's value is not omitted and not the JSON
2157−// "null". To check if this field is omitted, use [param.IsOmitted].
2158−func (u ChatCompletionUserMessageParamContentUnion) IsPresent() bool {
2159− return !param.IsOmitted(u) && !u.IsNull()
2160−}
2161func (u ChatCompletionUserMessageParamContentUnion) MarshalJSON() ([]byte, error) {
2077func (u ChatCompletionUserMessageParamContentUnion) MarshalJSON() ([]byte, error) {
2078+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfContentParts)
2079+}
2162− return param.MarshalUnion[ChatCompletionUserMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts)
2080+func (u *ChatCompletionUserMessageParamContentUnion) UnmarshalJSON(data []byte) error {
2081+ return apijson.UnmarshalRoot(data, u)
2163}
2082}
2164
2083
2165func (u *ChatCompletionUserMessageParamContentUnion) asAny() any {
2084func (u *ChatCompletionUserMessageParamContentUnion) asAny() any {
@@ -2179,7 +2098,7 @@ type ChatCompletionNewParams struct {
2179 // [images](https://platform.openai.com/docs/guides/vision), and
2098 // [images](https://platform.openai.com/docs/guides/vision), and
2180 // [audio](https://platform.openai.com/docs/guides/audio).
2099 // [audio](https://platform.openai.com/docs/guides/audio).
2181 Messages []ChatCompletionMessageParamUnion `json:"messages,omitzero,required"`
2100 Messages []ChatCompletionMessageParamUnion `json:"messages,omitzero,required"`
2182− // Model ID used to generate the response, like `gpt-4o` or `o1`. OpenAI offers a
2101+ // Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a
2183 // wide range of models with different capabilities, performance characteristics,
2102 // wide range of models with different capabilities, performance characteristics,
2184 // and price points. Refer to the
2103 // and price points. Refer to the
2185 // [model guide](https://platform.openai.com/docs/models) to browse and compare
2104 // [model guide](https://platform.openai.com/docs/models) to browse and compare
@@ -2203,7 +2122,7 @@ type ChatCompletionNewParams struct {
2203 //
2122 //
2204 // This value is now deprecated in favor of `max_completion_tokens`, and is not
2123 // This value is now deprecated in favor of `max_completion_tokens`, and is not
2205 // compatible with
2124 // compatible with
2206− // [o1 series models](https://platform.openai.com/docs/guides/reasoning).
2125+ // [o-series models](https://platform.openai.com/docs/guides/reasoning).
2207 MaxTokens param.Opt[int64] `json:"max_tokens,omitzero"`
2126 MaxTokens param.Opt[int64] `json:"max_tokens,omitzero"`
2208 // How many chat completion choices to generate for each input message. Note that
2127 // How many chat completion choices to generate for each input message. Note that
2209 // you will be charged based on the number of generated tokens across all of the
2128 // you will be charged based on the number of generated tokens across all of the
@@ -2222,6 +2141,8 @@ type ChatCompletionNewParams struct {
2222 // Whether or not to store the output of this chat completion request for use in
2141 // Whether or not to store the output of this chat completion request for use in
2223 // our [model distillation](https://platform.openai.com/docs/guides/distillation)
2142 // our [model distillation](https://platform.openai.com/docs/guides/distillation)
2224 // or [evals](https://platform.openai.com/docs/guides/evals) products.
2143 // or [evals](https://platform.openai.com/docs/guides/evals) products.
2144+ //
2145+ // Supports text and image inputs. Note: image inputs over 10MB will be dropped.
2225 Store param.Opt[bool] `json:"store,omitzero"`
2146 Store param.Opt[bool] `json:"store,omitzero"`
2226 // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will
2147 // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will
2227 // make the output more random, while lower values like 0.2 will make it more
2148 // make the output more random, while lower values like 0.2 will make it more
@@ -2242,8 +2163,8 @@ type ChatCompletionNewParams struct {
2242 // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling)
2163 // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling)
2243 // during tool use.
2164 // during tool use.
2244 ParallelToolCalls param.Opt[bool] `json:"parallel_tool_calls,omitzero"`
2165 ParallelToolCalls param.Opt[bool] `json:"parallel_tool_calls,omitzero"`
2245− // A unique identifier representing your end-user, which can help OpenAI to monitor
2166+ // A stable identifier for your end-users. Used to boost cache hit rates by better
2246− // and detect abuse.
2167+ // bucketing similar requests and to help OpenAI detect and prevent abuse.
2247 // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids).
2168 // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids).
2248 User param.Opt[string] `json:"user,omitzero"`
2169 User param.Opt[string] `json:"user,omitzero"`
2249 // Parameters for audio output. Required when audio output is requested with
2170 // Parameters for audio output. Required when audio output is requested with
@@ -2265,7 +2186,7 @@ type ChatCompletionNewParams struct {
2265 //
2186 //
2266 // Keys are strings with a maximum length of 64 characters. Values are strings with
2187 // Keys are strings with a maximum length of 64 characters. Values are strings with
2267 // a maximum length of 512 characters.
2188 // a maximum length of 512 characters.
2268− Metadata shared.MetadataParam `json:"metadata,omitzero"`
2189+ Metadata shared.Metadata `json:"metadata,omitzero"`
2269 // Output types that you would like the model to generate. Most models are capable
2190 // Output types that you would like the model to generate. Most models are capable
2270 // of generating text, which is the default:
2191 // of generating text, which is the default:
2271 //
2192 //
@@ -2276,6 +2197,8 @@ type ChatCompletionNewParams struct {
2276 // this model generate both text and audio responses, you can use:
2197 // this model generate both text and audio responses, you can use:
2277 //
2198 //
2278 // `["text", "audio"]`
2199 // `["text", "audio"]`
2200+ //
2201+ // Any of "text", "audio".
2279 Modalities []string `json:"modalities,omitzero"`
2202 Modalities []string `json:"modalities,omitzero"`
2280 // **o-series models only**
2203 // **o-series models only**
2281 //
2204 //
@@ -2286,23 +2209,28 @@ type ChatCompletionNewParams struct {
2286 //
2209 //
2287 // Any of "low", "medium", "high".
2210 // Any of "low", "medium", "high".
2288 ReasoningEffort shared.ReasoningEffort `json:"reasoning_effort,omitzero"`
2211 ReasoningEffort shared.ReasoningEffort `json:"reasoning_effort,omitzero"`
2289− // Specifies the latency tier to use for processing the request. This parameter is
2212+ // Specifies the processing type used for serving the request.
2290− // relevant for customers subscribed to the scale tier service:
2213+ //
2291− //
2214+ // - If set to 'auto', then the request will be processed with the service tier
2292− // - If set to 'auto', and the Project is Scale tier enabled, the system will
2215+ // configured in the Project settings. Unless otherwise configured, the Project
2293− // utilize scale tier credits until they are exhausted.
2216+ // will use 'default'.
2294− // - If set to 'auto', and the Project is not Scale tier enabled, the request will
2217+ // - If set to 'default', then the requset will be processed with the standard
2295− // be processed using the default service tier with a lower uptime SLA and no
2218+ // pricing and performance for the selected model.
2296− // latency guarentee.
2219+ // - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or
2297− // - If set to 'default', the request will be processed using the default service
2220+ // 'priority', then the request will be processed with the corresponding service
2298− // tier with a lower uptime SLA and no latency guarentee.
2221+ // tier. [Contact sales](https://openai.com/contact-sales) to learn more about
2222+ // Priority processing.
2299 // - When not set, the default behavior is 'auto'.
2223 // - When not set, the default behavior is 'auto'.
2300 //
2224 //
2301− // When this parameter is set, the response body will include the `service_tier`
2225+ // When the `service_tier` parameter is set, the response body will include the
2302− // utilized.
2226+ // `service_tier` value based on the processing mode actually used to serve the
2227+ // request. This response value may be different from the value set in the
2228+ // parameter.
2303 //
2229 //
2304− // Any of "auto", "default".
2230+ // Any of "auto", "default", "flex", "scale", "priority".
2305 ServiceTier ChatCompletionNewParamsServiceTier `json:"service_tier,omitzero"`
2231 ServiceTier ChatCompletionNewParamsServiceTier `json:"service_tier,omitzero"`
2232+ // Not supported with latest reasoning models `o3` and `o4-mini`.
2233+ //
2306 // Up to 4 sequences where the API will stop generating further tokens. The
2234 // Up to 4 sequences where the API will stop generating further tokens. The
2307 // returned text will not contain the stop sequence.
2235 // returned text will not contain the stop sequence.
2308 Stop ChatCompletionNewParamsStopUnion `json:"stop,omitzero"`
2236 Stop ChatCompletionNewParamsStopUnion `json:"stop,omitzero"`
@@ -2362,14 +2290,13 @@ type ChatCompletionNewParams struct {
2362 paramObj
2290 paramObj
2363}
2291}
2364
2292
2365−// IsPresent returns true if the field's value is not omitted and not the JSON
2366−// "null". To check if this field is omitted, use [param.IsOmitted].
2367−func (f ChatCompletionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2368−
2369func (r ChatCompletionNewParams) MarshalJSON() (data []byte, err error) {
2293func (r ChatCompletionNewParams) MarshalJSON() (data []byte, err error) {
2370 type shadow ChatCompletionNewParams
2294 type shadow ChatCompletionNewParams
2371 return param.MarshalObject(r, (*shadow)(&r))
2295 return param.MarshalObject(r, (*shadow)(&r))
2372}
2296}
2297+func (r *ChatCompletionNewParams) UnmarshalJSON(data []byte) error {
2298+ return apijson.UnmarshalRoot(data, r)
2299+}
2373
2300
2374// Only one field can be non-zero.
2301// Only one field can be non-zero.
2375//
2302//
@@ -2381,13 +2308,11 @@ type ChatCompletionNewParamsFunctionCallUnion struct {
2381 paramUnion
2308 paramUnion
2382}
2309}
2383
2310
2384−// IsPresent returns true if the field's value is not omitted and not the JSON
2385−// "null". To check if this field is omitted, use [param.IsOmitted].
2386−func (u ChatCompletionNewParamsFunctionCallUnion) IsPresent() bool {
2387− return !param.IsOmitted(u) && !u.IsNull()
2388−}
2389func (u ChatCompletionNewParamsFunctionCallUnion) MarshalJSON() ([]byte, error) {
2311func (u ChatCompletionNewParamsFunctionCallUnion) MarshalJSON() ([]byte, error) {
2312+ return param.MarshalUnion(u, u.OfFunctionCallMode, u.OfFunctionCallOption)
2313+}
2390− return param.MarshalUnion[ChatCompletionNewParamsFunctionCallUnion](u.OfFunctionCallMode, u.OfFunctionCallOption)
2314+func (u *ChatCompletionNewParamsFunctionCallUnion) UnmarshalJSON(data []byte) error {
2315+ return apijson.UnmarshalRoot(data, u)
2391}
2316}
2392
2317
2393func (u *ChatCompletionNewParamsFunctionCallUnion) asAny() any {
2318func (u *ChatCompletionNewParamsFunctionCallUnion) asAny() any {
@@ -2399,13 +2324,15 @@ func (u *ChatCompletionNewParamsFunctionCallUnion) asAny() any {
2399 return nil
2324 return nil
2400}
2325}
2401
2326
2402−// Returns a pointer to the underlying variant's property, if present.
2327+// `none` means the model will not call a function and instead generates a message.
2403−func (u ChatCompletionNewParamsFunctionCallUnion) GetName() *string {
2328+// `auto` means the model can pick between generating a message or calling a
2404− if vt := u.OfFunctionCallOption; vt != nil {
2329+// function.
2405− return &vt.Name
2330+type ChatCompletionNewParamsFunctionCallFunctionCallMode string
2406− }
2331+
2407− return nil
2332+const (
2408−}
2333+ ChatCompletionNewParamsFunctionCallFunctionCallModeNone ChatCompletionNewParamsFunctionCallFunctionCallMode = "none"
2334+ ChatCompletionNewParamsFunctionCallFunctionCallModeAuto ChatCompletionNewParamsFunctionCallFunctionCallMode = "auto"
2335+)
2409
2336
2410// Deprecated: deprecated
2337// Deprecated: deprecated
2411//
2338//
@@ -2428,13 +2355,13 @@ type ChatCompletionNewParamsFunction struct {
2428 paramObj
2355 paramObj
2429}
2356}
2430
2357
2431−// IsPresent returns true if the field's value is not omitted and not the JSON
2432−// "null". To check if this field is omitted, use [param.IsOmitted].
2433−func (f ChatCompletionNewParamsFunction) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2434func (r ChatCompletionNewParamsFunction) MarshalJSON() (data []byte, err error) {
2358func (r ChatCompletionNewParamsFunction) MarshalJSON() (data []byte, err error) {
2435 type shadow ChatCompletionNewParamsFunction
2359 type shadow ChatCompletionNewParamsFunction
2436 return param.MarshalObject(r, (*shadow)(&r))
2360 return param.MarshalObject(r, (*shadow)(&r))
2437}
2361}
2362+func (r *ChatCompletionNewParamsFunction) UnmarshalJSON(data []byte) error {
2363+ return apijson.UnmarshalRoot(data, r)
2364+}
2438
2365
2439// Only one field can be non-zero.
2366// Only one field can be non-zero.
2440//
2367//
@@ -2446,13 +2373,11 @@ type ChatCompletionNewParamsResponseFormatUnion struct {
2446 paramUnion
2373 paramUnion
2447}
2374}
2448
2375
2449−// IsPresent returns true if the field's value is not omitted and not the JSON
2450−// "null". To check if this field is omitted, use [param.IsOmitted].
2451−func (u ChatCompletionNewParamsResponseFormatUnion) IsPresent() bool {
2452− return !param.IsOmitted(u) && !u.IsNull()
2453−}
2454func (u ChatCompletionNewParamsResponseFormatUnion) MarshalJSON() ([]byte, error) {
2376func (u ChatCompletionNewParamsResponseFormatUnion) MarshalJSON() ([]byte, error) {
2455− return param.MarshalUnion[ChatCompletionNewParamsResponseFormatUnion](u.OfText, u.OfJSONSchema, u.OfJSONObject)
2377+ return param.MarshalUnion(u, u.OfText, u.OfJSONSchema, u.OfJSONObject)
2378+}
2379+func (u *ChatCompletionNewParamsResponseFormatUnion) UnmarshalJSON(data []byte) error {
2380+ return apijson.UnmarshalRoot(data, u)
2456}
2381}
2457
2382
2458func (u *ChatCompletionNewParamsResponseFormatUnion) asAny() any {
2383func (u *ChatCompletionNewParamsResponseFormatUnion) asAny() any {
@@ -2486,48 +2411,54 @@ func (u ChatCompletionNewParamsResponseFormatUnion) GetType() *string {
2486 return nil
2411 return nil
2487}
2412}
2488
2413
2489−// Specifies the latency tier to use for processing the request. This parameter is
2414+// Specifies the processing type used for serving the request.
2490−// relevant for customers subscribed to the scale tier service:
2491//
2415//
2492−// - If set to 'auto', and the Project is Scale tier enabled, the system will
2416+// - If set to 'auto', then the request will be processed with the service tier
2493−// utilize scale tier credits until they are exhausted.
2417+// configured in the Project settings. Unless otherwise configured, the Project
2494−// - If set to 'auto', and the Project is not Scale tier enabled, the request will
2418+// will use 'default'.
2495−// be processed using the default service tier with a lower uptime SLA and no
2419+// - If set to 'default', then the requset will be processed with the standard
2496−// latency guarentee.
2420+// pricing and performance for the selected model.
2421+// - If set to '[flex](https://platform.openai.com/docs/guides/flex-processing)' or
2497−// - If set to 'default', the request will be processed using the default service
2422+// 'priority', then the request will be processed with the corresponding service
2498−// tier with a lower uptime SLA and no latency guarentee.
2423+// tier. [Contact sales](https://openai.com/contact-sales) to learn more about
2424+// Priority processing.
2499// - When not set, the default behavior is 'auto'.
2425// - When not set, the default behavior is 'auto'.
2500//
2426//
2501−// When this parameter is set, the response body will include the `service_tier`
2427+// When the `service_tier` parameter is set, the response body will include the
2502−// utilized.
2428+// `service_tier` value based on the processing mode actually used to serve the
2429+// request. This response value may be different from the value set in the
2430+// parameter.
2503type ChatCompletionNewParamsServiceTier string
2431type ChatCompletionNewParamsServiceTier string
2504
2432
2505const (
2433const (
2506− ChatCompletionNewParamsServiceTierAuto ChatCompletionNewParamsServiceTier = "auto"
2434+ ChatCompletionNewParamsServiceTierAuto ChatCompletionNewParamsServiceTier = "auto"
2507− ChatCompletionNewParamsServiceTierDefault ChatCompletionNewParamsServiceTier = "default"
2435+ ChatCompletionNewParamsServiceTierDefault ChatCompletionNewParamsServiceTier = "default"
2436+ ChatCompletionNewParamsServiceTierFlex ChatCompletionNewParamsServiceTier = "flex"
2437+ ChatCompletionNewParamsServiceTierScale ChatCompletionNewParamsServiceTier = "scale"
2438+ ChatCompletionNewParamsServiceTierPriority ChatCompletionNewParamsServiceTier = "priority"
2508)
2439)
2509
2440
2510// Only one field can be non-zero.
2441// Only one field can be non-zero.
2511//
2442//
2512// Use [param.IsOmitted] to confirm if a field is set.
2443// Use [param.IsOmitted] to confirm if a field is set.
2513type ChatCompletionNewParamsStopUnion struct {
2444type ChatCompletionNewParamsStopUnion struct {
2514− OfString param.Opt[string] `json:",omitzero,inline"`
2445+ OfString param.Opt[string] `json:",omitzero,inline"`
2515− OfChatCompletionNewsStopArray []string `json:",omitzero,inline"`
2446+ OfStringArray []string `json:",omitzero,inline"`
2516 paramUnion
2447 paramUnion
2517}
2448}
2518
2449
2519−// IsPresent returns true if the field's value is not omitted and not the JSON
2520−// "null". To check if this field is omitted, use [param.IsOmitted].
2521−func (u ChatCompletionNewParamsStopUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
2522func (u ChatCompletionNewParamsStopUnion) MarshalJSON() ([]byte, error) {
2450func (u ChatCompletionNewParamsStopUnion) MarshalJSON() ([]byte, error) {
2451+ return param.MarshalUnion(u, u.OfString, u.OfStringArray)
2452+}
2523− return param.MarshalUnion[ChatCompletionNewParamsStopUnion](u.OfString, u.OfChatCompletionNewsStopArray)
2453+func (u *ChatCompletionNewParamsStopUnion) UnmarshalJSON(data []byte) error {
2454+ return apijson.UnmarshalRoot(data, u)
2524}
2455}
2525
2456
2526func (u *ChatCompletionNewParamsStopUnion) asAny() any {
2457func (u *ChatCompletionNewParamsStopUnion) asAny() any {
2527 if !param.IsOmitted(u.OfString) {
2458 if !param.IsOmitted(u.OfString) {
2528 return &u.OfString.Value
2459 return &u.OfString.Value
2529− } else if !param.IsOmitted(u.OfChatCompletionNewsStopArray) {
2460+ } else if !param.IsOmitted(u.OfStringArray) {
2530− return &u.OfChatCompletionNewsStopArray
2461+ return &u.OfStringArray
2531 }
2462 }
2532 return nil
2463 return nil
2533}
2464}
@@ -2546,19 +2477,17 @@ type ChatCompletionNewParamsWebSearchOptions struct {
2546 paramObj
2477 paramObj
2547}
2478}
2548
2479
2549−// IsPresent returns true if the field's value is not omitted and not the JSON
2550−// "null". To check if this field is omitted, use [param.IsOmitted].
2551−func (f ChatCompletionNewParamsWebSearchOptions) IsPresent() bool {
2552− return !param.IsOmitted(f) && !f.IsNull()
2553−}
2554func (r ChatCompletionNewParamsWebSearchOptions) MarshalJSON() (data []byte, err error) {
2480func (r ChatCompletionNewParamsWebSearchOptions) MarshalJSON() (data []byte, err error) {
2555 type shadow ChatCompletionNewParamsWebSearchOptions
2481 type shadow ChatCompletionNewParamsWebSearchOptions
2556 return param.MarshalObject(r, (*shadow)(&r))
2482 return param.MarshalObject(r, (*shadow)(&r))
2557}
2483}
2484+func (r *ChatCompletionNewParamsWebSearchOptions) UnmarshalJSON(data []byte) error {
2485+ return apijson.UnmarshalRoot(data, r)
2486+}
2558
2487
2559func init() {
2488func init() {
2560 apijson.RegisterFieldValidator[ChatCompletionNewParamsWebSearchOptions](
2489 apijson.RegisterFieldValidator[ChatCompletionNewParamsWebSearchOptions](
2561− "SearchContextSize", false, "low", "medium", "high",
2490+ "search_context_size", "low", "medium", "high",
2562 )
2491 )
2563}
2492}
2564
2493
@@ -2575,15 +2504,13 @@ type ChatCompletionNewParamsWebSearchOptionsUserLocation struct {
2575 paramObj
2504 paramObj
2576}
2505}
2577
2506
2578−// IsPresent returns true if the field's value is not omitted and not the JSON
2579−// "null". To check if this field is omitted, use [param.IsOmitted].
2580−func (f ChatCompletionNewParamsWebSearchOptionsUserLocation) IsPresent() bool {
2581− return !param.IsOmitted(f) && !f.IsNull()
2582−}
2583func (r ChatCompletionNewParamsWebSearchOptionsUserLocation) MarshalJSON() (data []byte, err error) {
2507func (r ChatCompletionNewParamsWebSearchOptionsUserLocation) MarshalJSON() (data []byte, err error) {
2584 type shadow ChatCompletionNewParamsWebSearchOptionsUserLocation
2508 type shadow ChatCompletionNewParamsWebSearchOptionsUserLocation
2585 return param.MarshalObject(r, (*shadow)(&r))
2509 return param.MarshalObject(r, (*shadow)(&r))
2586}
2510}
2511+func (r *ChatCompletionNewParamsWebSearchOptionsUserLocation) UnmarshalJSON(data []byte) error {
2512+ return apijson.UnmarshalRoot(data, r)
2513+}
2587
2514
2588// Approximate location parameters for the search.
2515// Approximate location parameters for the search.
2589type ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate struct {
2516type ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate struct {
@@ -2600,15 +2527,13 @@ type ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate struct {
2600 paramObj
2527 paramObj
2601}
2528}
2602
2529
2603−// IsPresent returns true if the field's value is not omitted and not the JSON
2604−// "null". To check if this field is omitted, use [param.IsOmitted].
2605−func (f ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) IsPresent() bool {
2606− return !param.IsOmitted(f) && !f.IsNull()
2607−}
2608func (r ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) MarshalJSON() (data []byte, err error) {
2530func (r ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) MarshalJSON() (data []byte, err error) {
2609 type shadow ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate
2531 type shadow ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate
2610 return param.MarshalObject(r, (*shadow)(&r))
2532 return param.MarshalObject(r, (*shadow)(&r))
2611}
2533}
2534+func (r *ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) UnmarshalJSON(data []byte) error {
2535+ return apijson.UnmarshalRoot(data, r)
2536+}
2612
2537
2613type ChatCompletionUpdateParams struct {
2538type ChatCompletionUpdateParams struct {
2614 // Set of 16 key-value pairs that can be attached to an object. This can be useful
2539 // Set of 16 key-value pairs that can be attached to an object. This can be useful
@@ -2617,18 +2542,17 @@ type ChatCompletionUpdateParams struct {
2617 //
2542 //
2618 // Keys are strings with a maximum length of 64 characters. Values are strings with
2543 // Keys are strings with a maximum length of 64 characters. Values are strings with
2619 // a maximum length of 512 characters.
2544 // a maximum length of 512 characters.
2620− Metadata shared.MetadataParam `json:"metadata,omitzero,required"`
2545+ Metadata shared.Metadata `json:"metadata,omitzero,required"`
2621 paramObj
2546 paramObj
2622}
2547}
2623
2548
2624−// IsPresent returns true if the field's value is not omitted and not the JSON
2625−// "null". To check if this field is omitted, use [param.IsOmitted].
2626−func (f ChatCompletionUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2627−
2628func (r ChatCompletionUpdateParams) MarshalJSON() (data []byte, err error) {
2549func (r ChatCompletionUpdateParams) MarshalJSON() (data []byte, err error) {
2629 type shadow ChatCompletionUpdateParams
2550 type shadow ChatCompletionUpdateParams
2630 return param.MarshalObject(r, (*shadow)(&r))
2551 return param.MarshalObject(r, (*shadow)(&r))
2631}
2552}
2553+func (r *ChatCompletionUpdateParams) UnmarshalJSON(data []byte) error {
2554+ return apijson.UnmarshalRoot(data, r)
2555+}
2632
2556
2633type ChatCompletionListParams struct {
2557type ChatCompletionListParams struct {
2634 // Identifier for the last chat completion from the previous pagination request.
2558 // Identifier for the last chat completion from the previous pagination request.
@@ -2640,7 +2564,7 @@ type ChatCompletionListParams struct {
2640 // A list of metadata keys to filter the Chat Completions by. Example:
2564 // A list of metadata keys to filter the Chat Completions by. Example:
2641 //
2565 //
2642 // `metadata[key1]=value1&metadata[key2]=value2`
2566 // `metadata[key1]=value1&metadata[key2]=value2`
2643− Metadata shared.MetadataParam `query:"metadata,omitzero" json:"-"`
2567+ Metadata shared.Metadata `query:"metadata,omitzero" json:"-"`
2644 // Sort order for Chat Completions by timestamp. Use `asc` for ascending order or
2568 // Sort order for Chat Completions by timestamp. Use `asc` for ascending order or
2645 // `desc` for descending order. Defaults to `asc`.
2569 // `desc` for descending order. Defaults to `asc`.
2646 //
2570 //
@@ -2649,13 +2573,9 @@ type ChatCompletionListParams struct {
2649 paramObj
2573 paramObj
2650}
2574}
2651
2575
2652−// IsPresent returns true if the field's value is not omitted and not the JSON
2653−// "null". To check if this field is omitted, use [param.IsOmitted].
2654−func (f ChatCompletionListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
2655−
2656// URLQuery serializes [ChatCompletionListParams]'s query parameters as
2576// URLQuery serializes [ChatCompletionListParams]'s query parameters as
2657// `url.Values`.
2577// `url.Values`.
2658−func (r ChatCompletionListParams) URLQuery() (v url.Values) {
2578+func (r ChatCompletionListParams) URLQuery() (v url.Values, err error) {
2659 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
2579 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
2660 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
2580 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
2661 NestedFormat: apiquery.NestedQueryFormatBrackets,
2581 NestedFormat: apiquery.NestedQueryFormatBrackets,
vendor/github.com/openai/openai-go/chatcompletionmessage.go+1−5
@@ -77,13 +77,9 @@ type ChatCompletionMessageListParams struct {
77 paramObj
77 paramObj
78}
78}
79
79
80−// IsPresent returns true if the field's value is not omitted and not the JSON
81−// "null". To check if this field is omitted, use [param.IsOmitted].
82−func (f ChatCompletionMessageListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
83−
84// URLQuery serializes [ChatCompletionMessageListParams]'s query parameters as
80// URLQuery serializes [ChatCompletionMessageListParams]'s query parameters as
85// `url.Values`.
81// `url.Values`.
86−func (r ChatCompletionMessageListParams) URLQuery() (v url.Values) {
82+func (r ChatCompletionMessageListParams) URLQuery() (v url.Values, err error) {
87 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
83 return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
88 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
84 ArrayFormat: apiquery.ArrayQueryFormatBrackets,
89 NestedFormat: apiquery.NestedQueryFormatBrackets,
85 NestedFormat: apiquery.NestedQueryFormatBrackets,
vendor/github.com/openai/openai-go/client.go+25−10
@@ -10,6 +10,7 @@ import (
10 "github.com/openai/openai-go/internal/requestconfig"
10 "github.com/openai/openai-go/internal/requestconfig"
11 "github.com/openai/openai-go/option"
11 "github.com/openai/openai-go/option"
12 "github.com/openai/openai-go/responses"
12 "github.com/openai/openai-go/responses"
13+ "github.com/openai/openai-go/webhooks"
13)
14)
14
15
15// Client creates a struct with services and top level methods that help with
16// Client creates a struct with services and top level methods that help with
@@ -26,17 +27,24 @@ type Client struct {
26 Moderations ModerationService
27 Moderations ModerationService
27 Models ModelService
28 Models ModelService
28 FineTuning FineTuningService
29 FineTuning FineTuningService
30+ Graders GraderService
29 VectorStores VectorStoreService
31 VectorStores VectorStoreService
32+ Webhooks webhooks.WebhookService
30 Beta BetaService
33 Beta BetaService
31 Batches BatchService
34 Batches BatchService
32 Uploads UploadService
35 Uploads UploadService
33 Responses responses.ResponseService
36 Responses responses.ResponseService
37+ Containers ContainerService
34}
38}
35
39
36// DefaultClientOptions read from the environment (OPENAI_API_KEY, OPENAI_ORG_ID,
40// DefaultClientOptions read from the environment (OPENAI_API_KEY, OPENAI_ORG_ID,
41+// OPENAI_PROJECT_ID, OPENAI_WEBHOOK_SECRET, OPENAI_BASE_URL). This should be used
37−// OPENAI_PROJECT_ID). This should be used to initialize new clients.
42+// to initialize new clients.
38func DefaultClientOptions() []option.RequestOption {
43func DefaultClientOptions() []option.RequestOption {
39 defaults := []option.RequestOption{option.WithEnvironmentProduction()}
44 defaults := []option.RequestOption{option.WithEnvironmentProduction()}
45+ if o, ok := os.LookupEnv("OPENAI_BASE_URL"); ok {
46+ defaults = append(defaults, option.WithBaseURL(o))
47+ }
40 if o, ok := os.LookupEnv("OPENAI_API_KEY"); ok {
48 if o, ok := os.LookupEnv("OPENAI_API_KEY"); ok {
41 defaults = append(defaults, option.WithAPIKey(o))
49 defaults = append(defaults, option.WithAPIKey(o))
42 }
50 }
@@ -46,13 +54,17 @@ func DefaultClientOptions() []option.RequestOption {
46 if o, ok := os.LookupEnv("OPENAI_PROJECT_ID"); ok {
54 if o, ok := os.LookupEnv("OPENAI_PROJECT_ID"); ok {
47 defaults = append(defaults, option.WithProject(o))
55 defaults = append(defaults, option.WithProject(o))
48 }
56 }
57+ if o, ok := os.LookupEnv("OPENAI_WEBHOOK_SECRET"); ok {
58+ defaults = append(defaults, option.WithWebhookSecret(o))
59+ }
49 return defaults
60 return defaults
50}
61}
51
62
52// NewClient generates a new client with the default option read from the
63// NewClient generates a new client with the default option read from the
53−// environment (OPENAI_API_KEY, OPENAI_ORG_ID, OPENAI_PROJECT_ID). The option
64+// environment (OPENAI_API_KEY, OPENAI_ORG_ID, OPENAI_PROJECT_ID,
65+// OPENAI_WEBHOOK_SECRET, OPENAI_BASE_URL). The option passed in as arguments are
54−// passed in as arguments are applied after these default arguments, and all option
66+// applied after these default arguments, and all option will be passed down to the
55−// will be passed down to the services and requests that this client makes.
67+// services and requests that this client makes.
56func NewClient(opts ...option.RequestOption) (r Client) {
68func NewClient(opts ...option.RequestOption) (r Client) {
57 opts = append(DefaultClientOptions(), opts...)
69 opts = append(DefaultClientOptions(), opts...)
58
70
@@ -67,11 +79,14 @@ func NewClient(opts ...option.RequestOption) (r Client) {
67 r.Moderations = NewModerationService(opts...)
79 r.Moderations = NewModerationService(opts...)
68 r.Models = NewModelService(opts...)
80 r.Models = NewModelService(opts...)
69 r.FineTuning = NewFineTuningService(opts...)
81 r.FineTuning = NewFineTuningService(opts...)
82+ r.Graders = NewGraderService(opts...)
70 r.VectorStores = NewVectorStoreService(opts...)
83 r.VectorStores = NewVectorStoreService(opts...)
84+ r.Webhooks = webhooks.NewWebhookService(opts...)
71 r.Beta = NewBetaService(opts...)
85 r.Beta = NewBetaService(opts...)
72 r.Batches = NewBatchService(opts...)
86 r.Batches = NewBatchService(opts...)
73 r.Uploads = NewUploadService(opts...)
87 r.Uploads = NewUploadService(opts...)
74 r.Responses = responses.NewResponseService(opts...)
88 r.Responses = responses.NewResponseService(opts...)
89+ r.Containers = NewContainerService(opts...)
75
90
76 return
91 return
77}
92}
@@ -107,40 +122,40 @@ func NewClient(opts ...option.RequestOption) (r Client) {
107//
122//
108// For even greater flexibility, see [option.WithResponseInto] and
123// For even greater flexibility, see [option.WithResponseInto] and
109// [option.WithResponseBodyInto].
124// [option.WithResponseBodyInto].
110−func (r *Client) Execute(ctx context.Context, method string, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
125+func (r *Client) Execute(ctx context.Context, method string, path string, params any, res any, opts ...option.RequestOption) error {
111 opts = append(r.Options, opts...)
126 opts = append(r.Options, opts...)
112 return requestconfig.ExecuteNewRequest(ctx, method, path, params, res, opts...)
127 return requestconfig.ExecuteNewRequest(ctx, method, path, params, res, opts...)
113}
128}
114
129
115// Get makes a GET request with the given URL, params, and optionally deserializes
130// Get makes a GET request with the given URL, params, and optionally deserializes
116// to a response. See [Execute] documentation on the params and response.
131// to a response. See [Execute] documentation on the params and response.
117−func (r *Client) Get(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
132+func (r *Client) Get(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error {
118 return r.Execute(ctx, http.MethodGet, path, params, res, opts...)
133 return r.Execute(ctx, http.MethodGet, path, params, res, opts...)
119}
134}
120
135
121// Post makes a POST request with the given URL, params, and optionally
136// Post makes a POST request with the given URL, params, and optionally
122// deserializes to a response. See [Execute] documentation on the params and
137// deserializes to a response. See [Execute] documentation on the params and
123// response.
138// response.
124−func (r *Client) Post(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
139+func (r *Client) Post(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error {
125 return r.Execute(ctx, http.MethodPost, path, params, res, opts...)
140 return r.Execute(ctx, http.MethodPost, path, params, res, opts...)
126}
141}
127
142
128// Put makes a PUT request with the given URL, params, and optionally deserializes
143// Put makes a PUT request with the given URL, params, and optionally deserializes
129// to a response. See [Execute] documentation on the params and response.
144// to a response. See [Execute] documentation on the params and response.
130−func (r *Client) Put(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
145+func (r *Client) Put(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error {
131 return r.Execute(ctx, http.MethodPut, path, params, res, opts...)
146 return r.Execute(ctx, http.MethodPut, path, params, res, opts...)
132}
147}
133
148
134// Patch makes a PATCH request with the given URL, params, and optionally
149// Patch makes a PATCH request with the given URL, params, and optionally
135// deserializes to a response. See [Execute] documentation on the params and
150// deserializes to a response. See [Execute] documentation on the params and
136// response.
151// response.
137−func (r *Client) Patch(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
152+func (r *Client) Patch(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error {
138 return r.Execute(ctx, http.MethodPatch, path, params, res, opts...)
153 return r.Execute(ctx, http.MethodPatch, path, params, res, opts...)
139}
154}
140
155
141// Delete makes a DELETE request with the given URL, params, and optionally
156// Delete makes a DELETE request with the given URL, params, and optionally
142// deserializes to a response. See [Execute] documentation on the params and
157// deserializes to a response. See [Execute] documentation on the params and
143// response.
158// response.
144−func (r *Client) Delete(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
159+func (r *Client) Delete(ctx context.Context, path string, params any, res any, opts ...option.RequestOption) error {
145 return r.Execute(ctx, http.MethodDelete, path, params, res, opts...)
160 return r.Execute(ctx, http.MethodDelete, path, params, res, opts...)
146}
161}
vendor/github.com/openai/openai-go/completion.go+70−62
@@ -10,7 +10,7 @@ import (
10 "github.com/openai/openai-go/internal/requestconfig"
10 "github.com/openai/openai-go/internal/requestconfig"
11 "github.com/openai/openai-go/option"
11 "github.com/openai/openai-go/option"
12 "github.com/openai/openai-go/packages/param"
12 "github.com/openai/openai-go/packages/param"
13− "github.com/openai/openai-go/packages/resp"
13+ "github.com/openai/openai-go/packages/respjson"
14 "github.com/openai/openai-go/packages/ssestream"
14 "github.com/openai/openai-go/packages/ssestream"
15 "github.com/openai/openai-go/shared/constant"
15 "github.com/openai/openai-go/shared/constant"
16)
16)
@@ -75,17 +75,16 @@ type Completion struct {
75 SystemFingerprint string `json:"system_fingerprint"`
75 SystemFingerprint string `json:"system_fingerprint"`
76 // Usage statistics for the completion request.
76 // Usage statistics for the completion request.
77 Usage CompletionUsage `json:"usage"`
77 Usage CompletionUsage `json:"usage"`
78− // Metadata for the response, check the presence of optional fields with the
78+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
79− // [resp.Field.IsPresent] method.
80 JSON struct {
79 JSON struct {
81− ID resp.Field
80+ ID respjson.Field
82− Choices resp.Field
81+ Choices respjson.Field
83− Created resp.Field
82+ Created respjson.Field
84− Model resp.Field
83+ Model respjson.Field
85− Object resp.Field
84+ Object respjson.Field
86− SystemFingerprint resp.Field
85+ SystemFingerprint respjson.Field
87− Usage resp.Field
86+ Usage respjson.Field
88− ExtraFields map[string]resp.Field
87+ ExtraFields map[string]respjson.Field
89 raw string
88 raw string
90 } `json:"-"`
89 } `json:"-"`
91}
90}
@@ -107,14 +106,13 @@ type CompletionChoice struct {
107 Index int64 `json:"index,required"`
106 Index int64 `json:"index,required"`
108 Logprobs CompletionChoiceLogprobs `json:"logprobs,required"`
107 Logprobs CompletionChoiceLogprobs `json:"logprobs,required"`
109 Text string `json:"text,required"`
108 Text string `json:"text,required"`
110− // Metadata for the response, check the presence of optional fields with the
109+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
111− // [resp.Field.IsPresent] method.
112 JSON struct {
110 JSON struct {
113− FinishReason resp.Field
111+ FinishReason respjson.Field
114− Index resp.Field
112+ Index respjson.Field
115− Logprobs resp.Field
113+ Logprobs respjson.Field
116− Text resp.Field
114+ Text respjson.Field
117− ExtraFields map[string]resp.Field
115+ ExtraFields map[string]respjson.Field
118 raw string
116 raw string
119 } `json:"-"`
117 } `json:"-"`
120}
118}
@@ -142,14 +140,13 @@ type CompletionChoiceLogprobs struct {
142 TokenLogprobs []float64 `json:"token_logprobs"`
140 TokenLogprobs []float64 `json:"token_logprobs"`
143 Tokens []string `json:"tokens"`
141 Tokens []string `json:"tokens"`
144 TopLogprobs []map[string]float64 `json:"top_logprobs"`
142 TopLogprobs []map[string]float64 `json:"top_logprobs"`
145− // Metadata for the response, check the presence of optional fields with the
143+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
146− // [resp.Field.IsPresent] method.
147 JSON struct {
144 JSON struct {
148− TextOffset resp.Field
145+ TextOffset respjson.Field
149− TokenLogprobs resp.Field
146+ TokenLogprobs respjson.Field
150− Tokens resp.Field
147+ Tokens respjson.Field
151− TopLogprobs resp.Field
148+ TopLogprobs respjson.Field
152− ExtraFields map[string]resp.Field
149+ ExtraFields map[string]respjson.Field
153 raw string
150 raw string
154 } `json:"-"`
151 } `json:"-"`
155}
152}
@@ -172,15 +169,14 @@ type CompletionUsage struct {
172 CompletionTokensDetails CompletionUsageCompletionTokensDetails `json:"completion_tokens_details"`
169 CompletionTokensDetails CompletionUsageCompletionTokensDetails `json:"completion_tokens_details"`
173 // Breakdown of tokens used in the prompt.
170 // Breakdown of tokens used in the prompt.
174 PromptTokensDetails CompletionUsagePromptTokensDetails `json:"prompt_tokens_details"`
171 PromptTokensDetails CompletionUsagePromptTokensDetails `json:"prompt_tokens_details"`
175− // Metadata for the response, check the presence of optional fields with the
172+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
176− // [resp.Field.IsPresent] method.
177 JSON struct {
173 JSON struct {
178− CompletionTokens resp.Field
174+ CompletionTokens respjson.Field
179− PromptTokens resp.Field
175+ PromptTokens respjson.Field
180− TotalTokens resp.Field
176+ TotalTokens respjson.Field
181− CompletionTokensDetails resp.Field
177+ CompletionTokensDetails respjson.Field
182− PromptTokensDetails resp.Field
178+ PromptTokensDetails respjson.Field
183− ExtraFields map[string]resp.Field
179+ ExtraFields map[string]respjson.Field
184 raw string
180 raw string
185 } `json:"-"`
181 } `json:"-"`
186}
182}
@@ -205,14 +201,13 @@ type CompletionUsageCompletionTokensDetails struct {
205 // still counted in the total completion tokens for purposes of billing, output,
201 // still counted in the total completion tokens for purposes of billing, output,
206 // and context window limits.
202 // and context window limits.
207 RejectedPredictionTokens int64 `json:"rejected_prediction_tokens"`
203 RejectedPredictionTokens int64 `json:"rejected_prediction_tokens"`
208− // Metadata for the response, check the presence of optional fields with the
204+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
209− // [resp.Field.IsPresent] method.
210 JSON struct {
205 JSON struct {
211− AcceptedPredictionTokens resp.Field
206+ AcceptedPredictionTokens respjson.Field
212− AudioTokens resp.Field
207+ AudioTokens respjson.Field
213− ReasoningTokens resp.Field
208+ ReasoningTokens respjson.Field
214− RejectedPredictionTokens resp.Field
209+ RejectedPredictionTokens respjson.Field
215− ExtraFields map[string]resp.Field
210+ ExtraFields map[string]respjson.Field
216 raw string
211 raw string
217 } `json:"-"`
212 } `json:"-"`
218}
213}
@@ -229,12 +224,11 @@ type CompletionUsagePromptTokensDetails struct {
229 AudioTokens int64 `json:"audio_tokens"`
224 AudioTokens int64 `json:"audio_tokens"`
230 // Cached tokens present in the prompt.
225 // Cached tokens present in the prompt.
231 CachedTokens int64 `json:"cached_tokens"`
226 CachedTokens int64 `json:"cached_tokens"`
232− // Metadata for the response, check the presence of optional fields with the
227+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
233− // [resp.Field.IsPresent] method.
234 JSON struct {
228 JSON struct {
235− AudioTokens resp.Field
229+ AudioTokens respjson.Field
236− CachedTokens resp.Field
230+ CachedTokens respjson.Field
237− ExtraFields map[string]resp.Field
231+ ExtraFields map[string]respjson.Field
238 raw string
232 raw string
239 } `json:"-"`
233 } `json:"-"`
240}
234}
@@ -258,7 +252,7 @@ type CompletionNewParams struct {
258 // see all of your available models, or see our
252 // see all of your available models, or see our
259 // [Model overview](https://platform.openai.com/docs/models) for descriptions of
253 // [Model overview](https://platform.openai.com/docs/models) for descriptions of
260 // them.
254 // them.
261− Model string `json:"model,omitzero,required"`
255+ Model CompletionNewParamsModel `json:"model,omitzero,required"`
262 // Generates `best_of` completions server-side and returns the "best" (the one with
256 // Generates `best_of` completions server-side and returns the "best" (the one with
263 // the highest log probability per token). Results cannot be streamed.
257 // the highest log probability per token). Results cannot be streamed.
264 //
258 //
@@ -344,6 +338,8 @@ type CompletionNewParams struct {
344 // As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token
338 // As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token
345 // from being generated.
339 // from being generated.
346 LogitBias map[string]int64 `json:"logit_bias,omitzero"`
340 LogitBias map[string]int64 `json:"logit_bias,omitzero"`
341+ // Not supported with latest reasoning models `o3` and `o4-mini`.
342+ //
347 // Up to 4 sequences where the API will stop generating further tokens. The
343 // Up to 4 sequences where the API will stop generating further tokens. The
348 // returned text will not contain the stop sequence.
344 // returned text will not contain the stop sequence.
349 Stop CompletionNewParamsStopUnion `json:"stop,omitzero"`
345 Stop CompletionNewParamsStopUnion `json:"stop,omitzero"`
@@ -352,14 +348,26 @@ type CompletionNewParams struct {
352 paramObj
348 paramObj
353}
349}
354
350
355−// IsPresent returns true if the field's value is not omitted and not the JSON
356−// "null". To check if this field is omitted, use [param.IsOmitted].
357−func (f CompletionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
358−
359func (r CompletionNewParams) MarshalJSON() (data []byte, err error) {
351func (r CompletionNewParams) MarshalJSON() (data []byte, err error) {
360 type shadow CompletionNewParams
352 type shadow CompletionNewParams
361 return param.MarshalObject(r, (*shadow)(&r))
353 return param.MarshalObject(r, (*shadow)(&r))
362}
354}
355+func (r *CompletionNewParams) UnmarshalJSON(data []byte) error {
356+ return apijson.UnmarshalRoot(data, r)
357+}
358+
359+// ID of the model to use. You can use the
360+// [List models](https://platform.openai.com/docs/api-reference/models/list) API to
361+// see all of your available models, or see our
362+// [Model overview](https://platform.openai.com/docs/models) for descriptions of
363+// them.
364+type CompletionNewParamsModel string
365+
366+const (
367+ CompletionNewParamsModelGPT3_5TurboInstruct CompletionNewParamsModel = "gpt-3.5-turbo-instruct"
368+ CompletionNewParamsModelDavinci002 CompletionNewParamsModel = "davinci-002"
369+ CompletionNewParamsModelBabbage002 CompletionNewParamsModel = "babbage-002"
370+)
363
371
364// Only one field can be non-zero.
372// Only one field can be non-zero.
365//
373//
@@ -372,11 +380,11 @@ type CompletionNewParamsPromptUnion struct {
372 paramUnion
380 paramUnion
373}
381}
374
382
375−// IsPresent returns true if the field's value is not omitted and not the JSON
376−// "null". To check if this field is omitted, use [param.IsOmitted].
377−func (u CompletionNewParamsPromptUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
378func (u CompletionNewParamsPromptUnion) MarshalJSON() ([]byte, error) {
383func (u CompletionNewParamsPromptUnion) MarshalJSON() ([]byte, error) {
379− return param.MarshalUnion[CompletionNewParamsPromptUnion](u.OfString, u.OfArrayOfStrings, u.OfArrayOfTokens, u.OfArrayOfTokenArrays)
384+ return param.MarshalUnion(u, u.OfString, u.OfArrayOfStrings, u.OfArrayOfTokens, u.OfArrayOfTokenArrays)
385+}
386+func (u *CompletionNewParamsPromptUnion) UnmarshalJSON(data []byte) error {
387+ return apijson.UnmarshalRoot(data, u)
380}
388}
381
389
382func (u *CompletionNewParamsPromptUnion) asAny() any {
390func (u *CompletionNewParamsPromptUnion) asAny() any {
@@ -396,23 +404,23 @@ func (u *CompletionNewParamsPromptUnion) asAny() any {
396//
404//
397// Use [param.IsOmitted] to confirm if a field is set.
405// Use [param.IsOmitted] to confirm if a field is set.
398type CompletionNewParamsStopUnion struct {
406type CompletionNewParamsStopUnion struct {
399− OfString param.Opt[string] `json:",omitzero,inline"`
407+ OfString param.Opt[string] `json:",omitzero,inline"`
400− OfCompletionNewsStopArray []string `json:",omitzero,inline"`
408+ OfStringArray []string `json:",omitzero,inline"`
401 paramUnion
409 paramUnion
402}
410}
403
411
404−// IsPresent returns true if the field's value is not omitted and not the JSON
405−// "null". To check if this field is omitted, use [param.IsOmitted].
406−func (u CompletionNewParamsStopUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
407func (u CompletionNewParamsStopUnion) MarshalJSON() ([]byte, error) {
412func (u CompletionNewParamsStopUnion) MarshalJSON() ([]byte, error) {
408− return param.MarshalUnion[CompletionNewParamsStopUnion](u.OfString, u.OfCompletionNewsStopArray)
413+ return param.MarshalUnion(u, u.OfString, u.OfStringArray)
414+}
415+func (u *CompletionNewParamsStopUnion) UnmarshalJSON(data []byte) error {
416+ return apijson.UnmarshalRoot(data, u)
409}
417}
410
418
411func (u *CompletionNewParamsStopUnion) asAny() any {
419func (u *CompletionNewParamsStopUnion) asAny() any {
412 if !param.IsOmitted(u.OfString) {
420 if !param.IsOmitted(u.OfString) {
413 return &u.OfString.Value
421 return &u.OfString.Value
414− } else if !param.IsOmitted(u.OfCompletionNewsStopArray) {
422+ } else if !param.IsOmitted(u.OfStringArray) {
415− return &u.OfCompletionNewsStopArray
423+ return &u.OfStringArray
416 }
424 }
417 return nil
425 return nil
418}
426}
vendor/github.com/openai/openai-go/container.gonew file+352

This diff is too big to show here.

vendor/github.com/openai/openai-go/containerfile.gonew file+286

This diff is too big to show here.

vendor/github.com/openai/openai-go/containerfilecontent.gonew file+49

This diff is too big to show here.

vendor/github.com/openai/openai-go/embedding.go+27−30

This diff is too big to show here.

vendor/github.com/openai/openai-go/file.go+22−29

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuning.go+8−2

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningalpha.gonew file+28

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningalphagrader.gonew file+672

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningcheckpoint.gonew file+28

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningcheckpointpermission.gonew file+254

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningjob.go+160−796

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningjobcheckpoint.go+20−28

This diff is too big to show here.

vendor/github.com/openai/openai-go/finetuningmethod.gonew file+1487

This diff is too big to show here.

vendor/github.com/openai/openai-go/grader.gonew file+28

This diff is too big to show here.

vendor/github.com/openai/openai-go/gradergradermodel.gonew file+1179

This diff is too big to show here.

vendor/github.com/openai/openai-go/image.go+386−89

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apierror/apierror.go+7−8

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apiform/encoder.go+96−32

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apiform/richparam.go+6−6

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apijson/decoder.go+91−79

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apijson/encoder.go+3−9

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apijson/enum.go+91−33

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apijson/registry.go+11−2

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apijson/subfield.go+9−9

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apijson/union.go+111−10

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apiquery/encoder.go+115−59

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apiquery/query.go+11−6

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/apiquery/richparam.go+9−9

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/encoding/json/encode.go+3−10

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/encoding/json/sentinel/null.go+25−36

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/encoding/json/time.go+12−10

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/param/field.godeleted−27

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/paramutil/field.gonew file+30

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/param/union.go → vendor/github.com/openai/openai-go/internal/paramutil/union.gorenamed+3−2

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/requestconfig/requestconfig.go+60−18

This diff is too big to show here.

vendor/github.com/openai/openai-go/internal/version.go+1−1

This diff is too big to show here.

vendor/github.com/openai/openai-go/model.go+12−14

This diff is too big to show here.

vendor/github.com/openai/openai-go/moderation.go+108−102

This diff is too big to show here.

vendor/github.com/openai/openai-go/option/middleware.gonew file+38

This diff is too big to show here.

vendor/github.com/openai/openai-go/option/requestoption.go+55−14

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/pagination/pagination.go+21−13

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/param/encoder.go+33−57

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/param/null.gonew file+19

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/param/option.go+73−55

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/param/param.go+109−48

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/param/sentinel.godeleted−31

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/resp/resp.godeleted−56

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/respjson/respjson.gonew file+88

This diff is too big to show here.

vendor/github.com/openai/openai-go/packages/ssestream/ssestream.go+8−4

This diff is too big to show here.

vendor/github.com/openai/openai-go/polling.go+2−41

This diff is too big to show here.

vendor/github.com/openai/openai-go/responses/aliases.go+76−24

This diff is too big to show here.

vendor/github.com/openai/openai-go/responses/inputitem.go+14−16

This diff is too big to show here.

vendor/github.com/openai/openai-go/responses/response.go+8769−3514

This diff is too big to show here.

vendor/github.com/openai/openai-go/shared/constant/constants.go+346−145

This diff is too big to show here.

vendor/github.com/openai/openai-go/shared/shared.go+171−123

This diff is too big to show here.

vendor/github.com/openai/openai-go/streamaccumulator.go+6−6

This diff is too big to show here.

vendor/github.com/openai/openai-go/upload.go+18−21

This diff is too big to show here.

vendor/github.com/openai/openai-go/uploadpart.go+11−14

This diff is too big to show here.

vendor/github.com/openai/openai-go/vectorstore.go+129−150

This diff is too big to show here.

vendor/github.com/openai/openai-go/vectorstorefile.go+43−57

This diff is too big to show here.

vendor/github.com/openai/openai-go/vectorstorefilebatch.go+24−35

This diff is too big to show here.

vendor/github.com/openai/openai-go/webhooks/aliases.gonew file+440

This diff is too big to show here.

vendor/github.com/openai/openai-go/webhooks/webhook.gonew file+1208

This diff is too big to show here.

vendor/github.com/spf13/cast/.gitignorenew file+25

This diff is too big to show here.

vendor/github.com/spf13/cast/LICENSEnew file+21

This diff is too big to show here.

vendor/github.com/spf13/cast/Makefilenew file+40

This diff is too big to show here.

vendor/github.com/spf13/cast/README.mdnew file+75

This diff is too big to show here.

vendor/github.com/spf13/cast/cast.gonew file+176

This diff is too big to show here.

vendor/github.com/spf13/cast/caste.gonew file+1510

This diff is too big to show here.

vendor/github.com/spf13/cast/timeformattype_string.gonew file+27

This diff is too big to show here.

vendor/modules.txt+16−9

This diff is too big to show here.