openai

package
v0.9.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 29, 2026 License: MIT Imports: 14 Imported by: 0

README

OpenAI Compatibility Package

This package provides types and utilities for building OpenAI-compatible APIs that use MCP tools. It bridges the gap between MCP's tool format and OpenAI's function calling format, and includes a client for seamless integration with MCP servers.

Installation

import "github.com/paularlott/mcp/openai"

Features

  • OpenAI Types: Complete request/response types for chat completions
  • Tool Conversion: Convert MCP tools to OpenAI function format
  • Response Extraction: Extract string results from MCP tool responses
  • Streaming Support: Iterator and accumulator for streaming responses
  • Tool Handlers: Event notifications during tool execution
  • Client Integration: Ready-to-use OpenAI client with automatic MCP server tool execution
  • Custom Tools: Support for tools sent to AI but executed manually by your code

Client Overview

The Client struct provides a high-level interface for OpenAI API interactions with built-in MCP server support. It automatically executes tools from attached MCP servers while allowing custom tools to be handled manually.

Key Components
  • Local Server: A single MCP server without namespace (optional)
  • Remote Servers: Multiple MCP servers with namespaces for routing tool calls
  • Custom Tools: Tools sent to AI but not executed by the client
  • Automatic Tool Execution: Tools from MCP servers are executed automatically during chat completions
Configuration
client, err := openai.New(openai.Config{
    APIKey: "sk-...",
    BaseURL: "https://api.openai.com/v1", // optional, defaults to OpenAI
    LocalServer: myMCPServer, // optional local MCP server
    ExtraHeaders: http.Header{           // optional custom headers for all requests
        "X-Custom-Header": []string{"value"},
    },
    RemoteServerConfigs: []openai.RemoteServerConfig{
        {
            BaseURL: "http://localhost:8080",
            Auth:    myAuthProvider,
            Namespace: "remote1",
        },
    },
})

// Add more remote servers dynamically
client.AddRemoteServer(openai.RemoteServerConfig{
    BaseURL: "http://localhost:8081",
    Auth:    anotherAuthProvider,
    Namespace: "remote2",
})

// Set custom tools (sent to AI but not executed)
client.SetCustomTools([]openai.Tool{...})
Chat Completions with Tool Execution

The client automatically handles tool calls from MCP servers:

req := openai.ChatCompletionRequest{
    Model: "gpt-4",
    Messages: []openai.Message{
        {Role: "user", Content: "What's the weather?"},
    },
}

response, err := client.ChatCompletion(ctx, req)
// Tool calls from MCP servers are executed automatically
// Custom tools are returned in the response for manual handling
Streaming Completions
stream := client.StreamChatCompletion(ctx, req)

for stream.Next() {
    chunk := stream.Current()
    // Process chunks...
    // Tool execution happens automatically during streaming
}

if err := stream.Err(); err != nil {
    // Handle error
}

Quick Start

Using the Client with MCP Servers
import (
    "context"
    "github.com/paularlott/mcp"
    "github.com/paularlott/mcp/openai"
)

// Create MCP server
server := mcp.NewServer("my-server", "1.0.0")
server.RegisterTool(/* ... */)

// Create OpenAI client with MCP integration
client, err := openai.New(openai.Config{
    APIKey: "sk-...",
    LocalServer: server, // Attach local MCP server
})
if err != nil {
    panic(err)
}

// Make a chat completion - tools are automatically available and executed
req := openai.ChatCompletionRequest{
    Model: "gpt-4",
    Messages: []openai.Message{
        {Role: "user", Content: "Use my tools to help"},
    },
}

response, err := client.ChatCompletion(context.Background(), req)
// Tool calls are executed automatically if needed
Converting MCP Tools to OpenAI Format
import (
    "github.com/paularlott/mcp"
    "github.com/paularlott/mcp/openai"
)

// Create your MCP server
server := mcp.NewServer("my-server", "1.0.0")
server.RegisterTool(/* ... */)

// Convert MCP tools to OpenAI format
mcpTools := server.ListTools()
openAITools := openai.MCPToolsToOpenAI(mcpTools)

// Or filter tools by name
filteredTools := openai.MCPToolsToOpenAIFiltered(mcpTools, openai.ToolsByName("search", "calculate"))

// Or exclude certain tools
excludedTools := openai.MCPToolsToOpenAIFiltered(mcpTools, openai.ExcludeTools("dangerous_tool"))
Extracting Tool Results
// After executing an MCP tool
response, err := server.CallTool(ctx, toolName, args)
if err != nil {
    return err
}

// Extract the result as a string for OpenAI
result, err := openai.ExtractToolResult(response)
if err != nil {
    return err
}

// Create tool result message
toolResultMessage := openai.Message{
    Role:       "tool",
    ToolCallID: toolCall.ID,
}
toolResultMessage.SetContentAsString(result)
Streaming with ChatStream
// Assuming you have response and error channels from your streaming implementation
stream := openai.NewChatStream(ctx, responseChan, errorChan)

for stream.Next() {
    chunk := stream.Current()

    // Process each chunk
    for _, choice := range chunk.Choices {
        if choice.Delta.Content != "" {
            fmt.Print(choice.Delta.Content)
        }
    }
}

if err := stream.Err(); err != nil {
    log.Printf("Stream error: %v", err)
}
Accumulating Streaming Responses (Optional)

The client automatically accumulates streaming responses internally to build tool calls and track usage. However, if you need to manually accumulate content or tool calls for custom processing, you can use CompletionAccumulator:

acc := &openai.CompletionAccumulator{}

for stream.Next() {
    chunk := stream.Current()
    acc.AddChunk(chunk)
}

// Check what we got
if content, ok := acc.FinishedContent(); ok {
    fmt.Println("Content:", content)
}

if toolCalls, ok := acc.FinishedToolCalls(); ok {
    for _, tc := range toolCalls {
        fmt.Printf("Tool call: %s(%v)\n", tc.Function.Name, tc.Function.Arguments)
    }
}

if refusal, ok := acc.FinishedRefusal(); ok {
    fmt.Println("Refusal:", refusal)
}

Note: For token usage, you don't need to accumulate manually. The client automatically injects usage estimates into responses when the upstream doesn't provide them. See Token Usage for details.


### Using Tool Handlers

Tool handlers receive events during tool execution, useful for sending SSE events or logging.

**Important:** The expected call order is:

1. `OnToolCall()` - called BEFORE executing the tool
2. Execute the tool
3. `OnToolResult()` - called AFTER the tool completes

```go
type MyToolHandler struct{}

func (h *MyToolHandler) OnToolCall(toolCall openai.ToolCall) error {
    log.Printf("Starting tool: %s", toolCall.Function.Name)
    return nil
}

func (h *MyToolHandler) OnToolResult(toolCallID, toolName, result string) error {
    log.Printf("Tool %s completed with result: %s", toolName, result)
    return nil
}

// Attach handler to context
ctx = openai.WithToolHandler(ctx, &MyToolHandler{})

// Later, retrieve and use it during tool processing
if handler := openai.ToolHandlerFromContext(ctx); handler != nil {
    // 1. Notify BEFORE execution
    handler.OnToolCall(toolCall)

    // 2. Execute the tool
    result, err := mcpServer.CallTool(ctx, toolCall.Function.Name, toolCall.Function.Arguments)

    // 3. Notify AFTER execution with result
    handler.OnToolResult(toolCall.ID, toolCall.Function.Name, result)
}

Types Reference

Request/Response Types
Type Description
ChatCompletionRequest OpenAI chat completion request
ChatCompletionResponse OpenAI chat completion response
Message Chat message with role, content, tool calls
Choice Response choice with message or delta
Delta Streaming delta content
Usage Token usage statistics
Tool Types
Type Description
Tool OpenAI tool definition
ToolFunction Function schema for a tool
ToolCall Tool call from assistant
ToolCallFunction Function name and arguments
DeltaToolCall Streaming tool call delta
DeltaFunction Streaming function delta
Message Content Helpers
// Get content as string (handles both string and array formats)
content := message.GetContentAsString()

// Set content as string
message.SetContentAsString("Hello, world!")
Tool Call JSON Handling

The ToolCallFunction type includes custom JSON marshaling/unmarshaling to handle OpenAI's format where arguments are a JSON string rather than an object:

// When marshaling to JSON, arguments become a string:
// {"name": "search", "arguments": "{\"query\": \"hello\"}"}

// When unmarshaling, the string is parsed back to map[string]any

Tool Filtering

Several filter helpers are provided:

// Include all tools
openai.AllTools()

// Include only specific tools
openai.ToolsByName("tool1", "tool2")

// Exclude specific tools
openai.ExcludeTools("admin_tool", "debug_tool")

// Custom filter
customFilter := func(name string) bool {
    return strings.HasPrefix(name, "public_")
}

Generating Tool Call IDs

When streaming, some LLMs don't provide tool call IDs. Generate one:

id := openai.GenerateToolCallID(index)
// Returns something like "call_a1b2c3d4e5f6..."

SSE Tool Status Events

When streaming chat completions with server-side tool processing, you can send tool execution status events to clients. These events are sent as SSE comments (prefixed with :) so standard SSE clients ignore them, but custom clients can parse them to show tool execution progress in the UI.

Event Format

Tool events are sent as SSE comments in the format :eventType:jsonData:

:tool_start:{"tool_call_id":"call_abc123","tool_name":"search","status":"running"}

:tool_end:{"tool_call_id":"call_abc123","tool_name":"search","status":"complete","result":"Search found 5 results..."}

The tool_end event includes the tool's result, allowing clients to display what the tool returned.

Using SSEToolHandler

The SSEToolHandler implements ToolHandler to automatically send tool events during execution:

// Create an SSE event writer (adapt to your HTTP framework)
sseWriter := openai.NewSimpleSSEWriter(responseWriter, func() {
    if f, ok := responseWriter.(http.Flusher); ok {
        f.Flush()
    }
})

// Create the tool handler with optional error logging
toolHandler := openai.NewSSEToolHandler(sseWriter, func(err error, eventType, toolName string) {
    log.Printf("Failed to write %s event for %s: %v", eventType, toolName, err)
})

// Attach to context for use during tool execution
ctx = openai.WithToolHandler(ctx, toolHandler)

// During tool processing, call in order:
// 1. toolHandler.OnToolCall(toolCall)  <- sends :tool_start: event
// 2. Execute the tool
// 3. toolHandler.OnToolResult(...)     <- sends :tool_end: event with result
Custom SSEEventWriter

For production use with your HTTP framework, implement the SSEEventWriter interface:

type SSEEventWriter interface {
    WriteEvent(eventType string, data any) error
}
Complete Stream Example

A streaming response with tool execution looks like:

data: {"id":"chatcmpl-xxx","choices":[{"delta":{"role":"assistant","content":"Let me look that up..."}}]}

:tool_start:{"tool_call_id":"call_abc","tool_name":"search","status":"running"}

:tool_end:{"tool_call_id":"call_abc","tool_name":"search","status":"complete","result":"Found 3 results for your query..."}

data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"Based on the search results..."}}]}

data: {"id":"chatcmpl-xxx","choices":[{"delta":{},"finish_reason":"stop"}]}

data: [DONE]
Parsing Tool Events (JavaScript)
const response = await fetch(url, options);
const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const text = decoder.decode(value);
  for (const line of text.split("\n")) {
    if (line.startsWith(":tool_start:")) {
      const event = JSON.parse(line.slice(":tool_start:".length));
      showSpinner(`Running ${event.tool_name}...`);
    } else if (line.startsWith(":tool_end:")) {
      const event = JSON.parse(line.slice(":tool_end:".length));
      hideSpinner(event.tool_name);
      // Optionally display the result
      if (event.result) {
        showToolResult(event.tool_name, event.result);
      }
    } else if (line.startsWith("data: ") && line !== "data: [DONE]") {
      const chunk = JSON.parse(line.slice(6));
      // Handle OpenAI chunk...
    }
  }
}

Complete Example

Here's a complete example of using the OpenAI client with MCP server integration:

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"

    "github.com/paularlott/mcp"
    "github.com/paularlott/mcp/openai"
)

func main() {
    // Create an MCP server with some tools
    server := mcp.NewServer("example-server", "1.0.0")

    // Register a simple tool
    server.RegisterTool(mcp.Tool{
        Name:        "get_weather",
        Description: "Get current weather for a location",
        InputSchema: mcp.ToolInputSchema{
            Type: "object",
            Properties: map[string]mcp.Property{
                "location": {Type: "string", Description: "City name"},
            },
            Required: []string{"location"},
        },
    }, func(ctx context.Context, args map[string]any) (*mcp.ToolResponse, error) {
        location := args["location"].(string)
        // Simulate weather lookup
        return &mcp.ToolResponse{
            Content: []mcp.Content{
                {Type: "text", Text: fmt.Sprintf("Weather in %s is sunny", location)},
            },
        }, nil
    })

    // Create OpenAI client with MCP server
    client, err := openai.New(openai.Config{
        APIKey:      "sk-your-api-key",
        LocalServer: server,
    })
    if err != nil {
        log.Fatal(err)
    }

    // Set up custom tools (optional - these won't be executed automatically)
    customTools := []openai.Tool{
        {
            Type: "function",
            Function: openai.ToolFunction{
                Name:        "send_email",
                Description: "Send an email",
                Parameters: map[string]any{
                    "type": "object",
                    "properties": map[string]any{
                        "to":      {"type": "string", "description": "Recipient email"},
                        "subject": {"type": "string", "description": "Email subject"},
                        "body":    {"type": "string", "description": "Email body"},
                    },
                    "required": []string{"to", "subject", "body"},
                },
            },
        },
    }
    client.SetCustomTools(customTools)

    // HTTP handler for chat completions
    http.HandleFunc("/chat/completions", func(w http.ResponseWriter, r *http.Request) {
        var req openai.ChatCompletionRequest
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        // The client automatically adds MCP tools and handles execution
        response, err := client.ChatCompletion(r.Context(), req)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        // If there are custom tool calls, handle them manually
        if len(response.Choices) > 0 {
            for _, toolCall := range response.Choices[0].Message.ToolCalls {
                if toolCall.Function.Name == "send_email" {
                    // Execute custom tool manually
                    args := toolCall.Function.Arguments
                    fmt.Printf("Sending email to %s: %s\n", args["to"], args["subject"])

                    // Add tool result to continue conversation
                    toolResult := openai.BuildToolResultMessage(toolCall.ID, "Email sent successfully")
                    req.Messages = append(req.Messages, response.Choices[0].Message)
                    req.Messages = append(req.Messages, toolResult)

                    // Make another completion with the result
                    response, err = client.ChatCompletion(r.Context(), req)
                    if err != nil {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
                    }
                    break
                }
            }
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(response)
    })

    log.Println("Server starting on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

This example shows:

  • Setting up an MCP server with tools
  • Creating an OpenAI client that integrates the server
  • Automatic execution of MCP tools
  • Manual handling of custom tools
  • Multi-turn conversations with tool results

Custom Tools

When you want to define tools that interact with your local system or application (rather than using MCP servers), you can set custom tools that will be sent to the AI but NOT executed by the client. Tool calls will be returned in the response for manual execution by your code.

SetCustomTools(tools []Tool)

Sets custom tools that will be included in AI requests but not auto-executed.

Parameters:

  • tools ([]Tool): Array of OpenAI tool definitions

Behavior:

  • Tools are sent to the AI in chat completion requests
  • When the AI calls a tool, the tool call is returned in the response
  • The client does NOT execute these tools automatically
  • Your code must handle tool execution manually

Example:

import (
    "github.com/paularlott/mcp/openai"
)

client, _ := openai.New(openai.Config{
    APIKey: "sk-...",
})

// Define custom tools
tools := []openai.Tool{
    {
        Type: "function",
        Function: openai.ToolFunction{
            Name:        "read_file",
            Description: "Read a file from the filesystem",
            Parameters: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "path": map[string]any{
                        "type":        "string",
                        "description": "File path",
                    },
                },
                "required": []string{"path"},
            },
        },
    },
}

client.SetCustomTools(tools)

// Make a chat completion
req := openai.ChatCompletionRequest{
    Model: "gpt-4",
    Messages: []openai.Message{
        {Role: "user", Content: "Read config.json"},
    },
}

response, _ := client.ChatCompletion(ctx, req)

// Check if AI wants to call a tool
if len(response.Choices) > 0 && len(response.Choices[0].Message.ToolCalls) > 0 {
    for _, toolCall := range response.Choices[0].Message.ToolCalls {
        // Execute the tool yourself
        if toolCall.Function.Name == "read_file" {
            path := toolCall.Function.Arguments["path"].(string)
            content := readFile(path)
            // Send result back to AI in next message...
        }
    }
}

See also: The scriptlingcoder example demonstrates using custom tools from Scriptling to build an AI coding assistant.

License

This package is part of the MCP library and is licensed under the same terms.

Token Usage

The client automatically populates the Usage field in responses. If the upstream LLM provides token counts, those are used directly. If not, the client automatically estimates usage and injects it into the response.

This means you can always rely on response.Usage being populated:

response, err := client.ChatCompletion(ctx, req)
if err != nil {
    return err
}

// Usage is always available (real or estimated)
fmt.Printf("Tokens used: %d prompt, %d completion\n",
    response.Usage.PromptTokens,
    response.Usage.CompletionTokens)
Manual Token Estimation

If you need to estimate tokens independently (e.g., for pre-flight checks or custom tracking), you can use TokenCounter directly:

// Initialize counter and estimate prompt tokens from initial messages
tokenCounter := openai.NewTokenCounter()
tokenCounter.AddPromptTokensFromMessages(req.Messages)

// After receiving streaming deltas, track completion tokens
tokenCounter.AddCompletionTokensFromDelta(&delta)

// Or for non-streaming, track from the full message
tokenCounter.AddCompletionTokensFromMessage(&response.Choices[0].Message)

// When tools are used, track tool result tokens (they become prompt tokens for next iteration)
toolResultMsg := openai.BuildToolResultMessage(toolCall.ID, result)
tokenCounter.AddPromptTokensFromMessages([]openai.Message{toolResultMsg})

// Get the estimated usage
usage := tokenCounter.GetUsage()
// usage.PromptTokens, usage.CompletionTokens, usage.TotalTokens
Token Estimation Algorithm

The EstimateTokens function provides a fast, reproducible approximation based on:

  • Word boundaries (using strings.Fields)
  • Punctuation counting (each punctuation mark = 1 token)
  • Chat template overhead (~4 tokens for conversation structure)
  • Per-message overhead (~3 tokens for role markers and special tokens)

This is suitable for billing estimates and UI display, but not for exact token limit calculations.

Documentation

Index

Constants

View Source
const (
	IncludeWebSearchSources      = "web_search_call.action.sources"
	IncludeCodeInterpreterOutput = "code_interpreter_call.outputs"
	IncludeComputerCallImage     = "computer_call_output.output.image_url"
	IncludeFileSearchResults     = "file_search_call.results"
	IncludeInputImageURL         = "message.input_image.image_url"
	IncludeOutputLogProbs        = "message.output_text.logprobs"
	IncludeReasoningEncrypted    = "reasoning.encrypted_content"
)

Common include options

View Source
const (
	// EventToolStart is sent when a tool execution begins
	EventToolStart = "tool_start"
	// EventToolEnd is sent when a tool execution completes
	EventToolEnd = "tool_end"
)

SSE event types for tool status notifications Standard OpenAI clients ignore these; custom clients can use them for UI feedback

View Source
const MAX_TOOL_CALL_ITERATIONS = 20

Variables

This section is empty.

Functions

func EstimateTokens added in v0.5.0

func EstimateTokens(text string) int

EstimateTokens returns a rough token count for a given input string. This uses a simple heuristic based on word boundaries and punctuation.

func ExtractAllTextContent

func ExtractAllTextContent(response *mcp.ToolResponse) string

ExtractAllTextContent extracts all text content from an MCP ToolResponse, concatenating multiple text parts with newlines.

func ExtractToolResult

func ExtractToolResult(response *mcp.ToolResponse) (string, error)

ExtractToolResult extracts a string result from an MCP ToolResponse for use in OpenAI tool result messages.

Priority order:

  1. StructuredContent - serialized to JSON
  2. First text content in Content array
  3. Default success message

func GenerateToolCallID

func GenerateToolCallID(index int) string

GenerateToolCallID creates a unique ID for tool calls. This is useful when LLMs don't provide an ID in streaming responses. The format matches OpenAI's tool call ID format: "call_" followed by random characters.

func GetToolNames added in v0.4.0

func GetToolNames(toolCalls []ToolCall) []string

GetToolNames returns the names of all tools in the provided tool calls.

func HasToolCalls added in v0.4.0

func HasToolCalls(msg Message) bool

HasToolCalls returns true if the message contains tool calls.

func MustParseToolArguments added in v0.4.0

func MustParseToolArguments(arguments map[string]any, target interface{})

MustParseToolArguments is like ParseToolArguments but panics on error. Use only in situations where you're certain the arguments are valid.

func ParseToolArguments added in v0.4.0

func ParseToolArguments(arguments map[string]any, target interface{}) error

ParseToolArguments parses the tool call arguments map into the provided struct. The target should be a pointer to the struct.

func WithToolHandler

func WithToolHandler(ctx context.Context, h ToolHandler) context.Context

WithToolHandler attaches a ToolHandler to the context. The handler will receive events during tool processing.

Types

type APIError added in v0.4.0

type APIError struct {
	StatusCode int    `json:"-"`
	Type       string `json:"type"`
	Message    string `json:"message"`
	Param      string `json:"param,omitempty"`
	Code       string `json:"code,omitempty"`
}

APIError represents an error returned by the OpenAI API.

func NewAuthenticationError added in v0.4.0

func NewAuthenticationError(message string) *APIError

NewAuthenticationError creates an authentication error.

func NewInvalidRequestError added in v0.4.0

func NewInvalidRequestError(message string) *APIError

NewInvalidRequestError creates an invalid request error.

func NewRateLimitError added in v0.4.0

func NewRateLimitError(message string) *APIError

NewRateLimitError creates a rate limit error.

func NewServerError added in v0.4.0

func NewServerError(message string) *APIError

NewServerError creates a server error.

func NewTokenLimitError added in v0.4.0

func NewTokenLimitError(message string) *APIError

NewTokenLimitError creates a token limit error.

func (*APIError) Error added in v0.4.0

func (e *APIError) Error() string

func (*APIError) IsAuthentication added in v0.4.0

func (e *APIError) IsAuthentication() bool

IsAuthentication returns true if this is an authentication error (401).

func (*APIError) IsInvalidRequest added in v0.4.0

func (e *APIError) IsInvalidRequest() bool

IsInvalidRequest returns true if this is an invalid request error (400).

func (*APIError) IsNotFound added in v0.4.0

func (e *APIError) IsNotFound() bool

IsNotFound returns true if this is a not found error (404).

func (*APIError) IsPermission added in v0.4.0

func (e *APIError) IsPermission() bool

IsPermission returns true if this is a permission error (403).

func (*APIError) IsRateLimit added in v0.4.0

func (e *APIError) IsRateLimit() bool

IsRateLimit returns true if this is a rate limit error (429).

func (*APIError) IsRetryable added in v0.4.0

func (e *APIError) IsRetryable() bool

IsRetryable returns true if this error is likely to succeed on retry.

func (*APIError) IsServerError added in v0.4.0

func (e *APIError) IsServerError() bool

IsServerError returns true if this is a server error (5xx).

func (*APIError) IsTokenLimit added in v0.4.0

func (e *APIError) IsTokenLimit() bool

IsTokenLimit returns true if this is a token limit error.

type ChatCompletionRequest

type ChatCompletionRequest struct {
	Model               string    `json:"model"`
	Messages            []Message `json:"messages"`
	Tools               []Tool    `json:"tools,omitempty"`
	MaxTokens           int       `json:"max_tokens,omitempty"`
	MaxCompletionTokens int       `json:"max_completion_tokens,omitempty"`
	Temperature         float32   `json:"temperature,omitempty"`
	ReasoningEffort     string    `json:"reasoning_effort,omitempty"`
	Stream              bool      `json:"stream"`
}

ChatCompletionRequest represents an OpenAI chat completion request

type ChatCompletionResponse

type ChatCompletionResponse struct {
	ID                string   `json:"id"`
	Object            string   `json:"object"`
	Created           int64    `json:"created"`
	Model             string   `json:"model"`
	SystemFingerprint string   `json:"system_fingerprint,omitempty"`
	Choices           []Choice `json:"choices"`
	Usage             *Usage   `json:"usage,omitempty"`
}

ChatCompletionResponse represents an OpenAI chat completion response

type ChatStream

type ChatStream struct {
	// contains filtered or unexported fields
}

ChatStream provides an iterator interface for streaming chat completion responses. It is designed to be used in a for loop pattern:

stream := openai.NewChatStream(ctx, responseChan, errorChan)
for stream.Next() {
    chunk := stream.Current()
    // process chunk
}
if err := stream.Err(); err != nil {
    // handle error
}

func NewChatStream

func NewChatStream(ctx context.Context, responseChan <-chan ChatCompletionResponse, errorChan <-chan error) *ChatStream

NewChatStream creates a new ChatStream from response and error channels.

func (*ChatStream) Current

func (s *ChatStream) Current() ChatCompletionResponse

Current returns the current response chunk. Must be called after Next returns true.

func (*ChatStream) Done

func (s *ChatStream) Done() bool

Done returns true if the stream has completed.

func (*ChatStream) Err

func (s *ChatStream) Err() error

Err returns any error that occurred during streaming. Should be checked after Next returns false.

func (*ChatStream) Next

func (s *ChatStream) Next() bool

Next advances to the next response chunk. Returns true if a chunk is available, false if the stream is done or an error occurred.

type Choice

type Choice struct {
	Index        int     `json:"index"`
	Message      Message `json:"message,omitempty"`
	Delta        Delta   `json:"delta,omitempty"`
	FinishReason string  `json:"finish_reason,omitempty"`
}

Choice represents a completion choice

type Client added in v0.8.0

type Client struct {
	// contains filtered or unexported fields
}

Client represents an OpenAI API client using the shared HTTP pool

func New added in v0.8.0

func New(config Config) (*Client, error)

New creates a new OpenAI client using the shared HTTP pool

func (*Client) AddRemoteServer added in v0.8.0

func (c *Client) AddRemoteServer(config RemoteServerConfig)

AddRemoteServer adds a remote MCP server. The namespace is derived from the client's namespace.

func (*Client) CancelResponse added in v0.8.0

func (c *Client) CancelResponse(ctx context.Context, id string) (*ResponseObject, error)

CancelResponse cancels a response by ID using the OpenAI Responses API https://platform.openai.com/docs/api-reference/responses/cancel

func (*Client) ChatCompletion added in v0.8.0

func (c *Client) ChatCompletion(ctx context.Context, req ChatCompletionRequest) (*ChatCompletionResponse, error)

ChatCompletion performs a non-streaming chat completion with automatic tool processing

func (*Client) CreateEmbedding added in v0.8.0

func (c *Client) CreateEmbedding(ctx context.Context, req EmbeddingRequest) (*EmbeddingResponse, error)

CreateEmbedding creates an embedding using the OpenAI Embeddings API https://platform.openai.com/docs/api-reference/embeddings/create

func (*Client) CreateResponse added in v0.8.0

func (c *Client) CreateResponse(ctx context.Context, req CreateResponseRequest) (*ResponseObject, error)

CreateResponse creates a new response using the OpenAI Responses API https://platform.openai.com/docs/api-reference/responses/create

func (*Client) GetAllTools added in v0.8.0

func (c *Client) GetAllTools(ctx context.Context) ([]mcp.MCPTool, error)

GetAllTools returns all tools from local and remote servers Local server tools are returned as-is Remote server tools are already namespaced by their client

func (*Client) GetCustomTools added in v0.8.0

func (c *Client) GetCustomTools() []Tool

GetCustomTools returns the custom tools.

func (*Client) GetLocalServer added in v0.8.0

func (c *Client) GetLocalServer() MCPServer

GetLocalServer returns the local MCP server

func (*Client) GetModels added in v0.8.0

func (c *Client) GetModels(ctx context.Context) (*ModelsResponse, error)

GetModels retrieves the list of available models from OpenAI

func (*Client) GetResponse added in v0.8.0

func (c *Client) GetResponse(ctx context.Context, id string) (*ResponseObject, error)

GetResponse retrieves a response by ID using the OpenAI Responses API https://platform.openai.com/docs/api-reference/responses/get

func (*Client) RemoveRemoteServer added in v0.8.0

func (c *Client) RemoveRemoteServer(namespace string)

RemoveRemoteServer removes a remote MCP server by namespace

func (*Client) SetCustomTools added in v0.8.0

func (c *Client) SetCustomTools(tools []Tool)

SetCustomTools sets custom tools that will be sent to the AI but not executed by the client. These tools are returned to the caller for manual execution.

func (*Client) StreamChatCompletion added in v0.8.0

func (c *Client) StreamChatCompletion(ctx context.Context, req ChatCompletionRequest) *ChatStream

StreamChatCompletion performs a streaming chat completion with automatic tool processing Returns a channel of pure OpenAI ChatCompletionResponse chunks

type CompletionAccumulator

type CompletionAccumulator struct {
	Choices []accumulatorChoice
}

CompletionAccumulator accumulates streaming chat completion chunks into complete responses. It handles the incremental building of content, tool calls, and refusals.

func (*CompletionAccumulator) AddChunk

func (acc *CompletionAccumulator) AddChunk(chunk ChatCompletionResponse)

AddChunk processes a streaming chunk and accumulates its content.

func (*CompletionAccumulator) Content

func (acc *CompletionAccumulator) Content() string

Content returns the current accumulated content for the first choice.

func (*CompletionAccumulator) FinishReason

func (acc *CompletionAccumulator) FinishReason() string

FinishReason returns the finish reason for the first choice.

func (*CompletionAccumulator) FinishedContent

func (acc *CompletionAccumulator) FinishedContent() (string, bool)

FinishedContent returns the accumulated content for the first choice if complete. Returns the content and true if finish_reason is "stop", otherwise empty string and false.

func (*CompletionAccumulator) FinishedRefusal

func (acc *CompletionAccumulator) FinishedRefusal() (string, bool)

FinishedRefusal returns the accumulated refusal for the first choice if present. Returns the refusal and true if there is refusal content, otherwise empty string and false.

func (*CompletionAccumulator) FinishedToolCall

func (acc *CompletionAccumulator) FinishedToolCall() (*ToolCall, bool)

FinishedToolCall returns the first accumulated tool call for the first choice if complete. Returns the tool call and true if finish_reason is "tool_calls", otherwise nil and false.

func (*CompletionAccumulator) FinishedToolCalls

func (acc *CompletionAccumulator) FinishedToolCalls() ([]ToolCall, bool)

FinishedToolCalls returns all accumulated tool calls for the first choice if complete. Returns the tool calls and true if finish_reason is "tool_calls", otherwise nil and false.

func (*CompletionAccumulator) IsComplete

func (acc *CompletionAccumulator) IsComplete() bool

IsComplete returns true if the first choice has a finish reason.

func (*CompletionAccumulator) Reset

func (acc *CompletionAccumulator) Reset()

Reset clears the accumulator for reuse.

type CompletionTokensDetails

type CompletionTokensDetails struct {
	ReasoningTokens          int `json:"reasoning_tokens"`
	AudioTokens              int `json:"audio_tokens"`
	AcceptedPredictionTokens int `json:"accepted_prediction_tokens"`
	RejectedPredictionTokens int `json:"rejected_prediction_tokens"`
}

CompletionTokensDetails represents detailed completion token usage

type Config added in v0.8.0

type Config struct {
	APIKey              string
	BaseURL             string
	LocalServer         MCPServer            // Local MCP server (no namespace)
	RemoteServerConfigs []RemoteServerConfig // Remote MCP server configs
	ExtraHeaders        http.Header          // Custom headers added to all requests
	HTTPPool            pool.HTTPPool        // Optional custom HTTP pool (nil = use default secure pool)
}

Config holds configuration for the OpenAI client

type ContentPart

type ContentPart struct {
	Type     string    `json:"type"`
	Text     string    `json:"text,omitempty"`
	ImageURL *ImageURL `json:"image_url,omitempty"`
}

ContentPart represents a multi-modal content part

func ImageBase64ContentPart added in v0.4.0

func ImageBase64ContentPart(base64Data string, mediaType string, detail string) ContentPart

ImageBase64ContentPart creates a ContentPart with a base64-encoded image. The mediaType should be something like "image/png" or "image/jpeg".

func ImageURLContentPart added in v0.4.0

func ImageURLContentPart(url string, detail string) ContentPart

ImageURLContentPart creates a ContentPart with an image URL.

func TextContentPart added in v0.4.0

func TextContentPart(text string) ContentPart

TextContentPart creates a ContentPart with text content.

type Conversation added in v0.6.11

type Conversation struct {
	ID        string                 `json:"id"`
	Object    string                 `json:"object"` // "conversation"
	CreatedAt int64                  `json:"created_at"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

Conversation represents a conversation object https://platform.openai.com/docs/api-reference/conversations/object

type ConversationDeleteResponse added in v0.6.11

type ConversationDeleteResponse struct {
	ID      string `json:"id"`
	Object  string `json:"object"` // "conversation.deleted"
	Deleted bool   `json:"deleted"`
}

ConversationDeleteResponse represents the response when deleting a conversation

type ConversationItem added in v0.6.11

type ConversationItem struct {
	Type    string        `json:"type"` // "message", "tool_call", "reasoning", etc.
	ID      string        `json:"id"`
	Status  string        `json:"status,omitempty"` // "completed", "incomplete", "in_progress"
	Role    string        `json:"role,omitempty"`   // "user", "assistant", "system"
	Content []ContentPart `json:"content,omitempty"`
	// Additional fields based on type
	ToolCall   *ToolCall              `json:"tool_call,omitempty"`
	ToolCallID string                 `json:"tool_call_id,omitempty"`
	Name       string                 `json:"name,omitempty"`
	Output     interface{}            `json:"output,omitempty"`
	Reasoning  map[string]interface{} `json:"reasoning,omitempty"`
}

ConversationItem represents an item in a conversation Items can be messages, tool calls, reasoning, etc.

type ConversationItemListResponse added in v0.6.11

type ConversationItemListResponse struct {
	Object  string             `json:"object"` // "list"
	Data    []ConversationItem `json:"data"`
	FirstID string             `json:"first_id,omitempty"`
	LastID  string             `json:"last_id,omitempty"`
	HasMore bool               `json:"has_more"`
}

ConversationItemListResponse represents a list of conversation items

type CreateConversationRequest added in v0.6.11

type CreateConversationRequest struct {
	Items    []ConversationItem     `json:"items,omitempty"`
	Metadata map[string]interface{} `json:"metadata,omitempty"`
}

CreateConversationRequest represents a request to create a conversation

type CreateItemsRequest added in v0.6.11

type CreateItemsRequest struct {
	Items []ConversationItem `json:"items"`
}

CreateItemsRequest represents a request to add items to a conversation

type CreateResponseRequest added in v0.6.9

type CreateResponseRequest struct {
	Model              string                 `json:"model"`
	Input              []any                  `json:"input,omitempty"`
	Modalities         []string               `json:"modalities,omitempty"`
	Instructions       string                 `json:"instructions,omitempty"`
	Tools              []Tool                 `json:"tools,omitempty"`
	PreviousResponseID string                 `json:"previous_response_id,omitempty"`
	Metadata           map[string]interface{} `json:"metadata,omitempty"`
	Background         bool                   `json:"background,omitempty"`
	MaxOutputTokens    *int                   `json:"max_output_tokens,omitempty"`
	ParallelToolCalls  *bool                  `json:"parallel_tool_calls,omitempty"`
	Store              *bool                  `json:"store,omitempty"`
	Temperature        *float64               `json:"temperature,omitempty"`
	TopP               *float64               `json:"top_p,omitempty"`
	Truncation         string                 `json:"truncation,omitempty"`
}

CreateResponseRequest represents a request to create a response

type Delta

type Delta struct {
	ReasoningContent string          `json:"reasoning_content,omitempty"`
	Role             string          `json:"role,omitempty"`
	Content          string          `json:"content,omitempty"`
	Refusal          string          `json:"refusal,omitempty"`
	ToolCalls        []DeltaToolCall `json:"tool_calls,omitempty"`
}

Delta represents a streaming delta

type DeltaFunction

type DeltaFunction struct {
	Name      string `json:"name,omitempty"`
	Arguments string `json:"arguments,omitempty"`
}

DeltaFunction represents a streaming function delta

type DeltaToolCall

type DeltaToolCall struct {
	Index    int           `json:"index"`
	ID       string        `json:"id,omitempty"`
	Type     string        `json:"type,omitempty"`
	Function DeltaFunction `json:"function,omitempty"`
}

DeltaToolCall represents a streaming tool call delta

type Embedding added in v0.6.7

type Embedding struct {
	Object    string    `json:"object"`
	Embedding []float64 `json:"embedding"`
	Index     int       `json:"index"`
}

Embedding represents a single embedding

type EmbeddingRequest added in v0.6.7

type EmbeddingRequest struct {
	Model          string      `json:"model"`
	Input          interface{} `json:"input"`
	EncodingFormat string      `json:"encoding_format,omitempty"`
	Dimensions     int         `json:"dimensions,omitempty"`
	User           string      `json:"user,omitempty"`
}

EmbeddingRequest represents an OpenAI embedding request

type EmbeddingResponse added in v0.6.7

type EmbeddingResponse struct {
	Object string      `json:"object"`
	Data   []Embedding `json:"data"`
	Model  string      `json:"model"`
	Usage  Usage       `json:"usage"`
}

EmbeddingResponse represents an OpenAI embedding response

type ErrorResponse added in v0.4.0

type ErrorResponse struct {
	Error *APIError `json:"error"`
}

ErrorResponse represents the error response structure from OpenAI API.

type ImageURL

type ImageURL struct {
	URL    string `json:"url"`
	Detail string `json:"detail,omitempty"`
}

ImageURL represents an image URL in content

type ItemIncludeOptions added in v0.6.11

type ItemIncludeOptions []string

ItemIncludeOptions represents the include parameter for listing items

type MCPServer added in v0.8.0

type MCPServer interface {
	ListTools() []mcp.MCPTool
	ListToolsWithContext(ctx context.Context) []mcp.MCPTool
	CallTool(ctx context.Context, name string, args map[string]any) (*mcp.ToolResponse, error)
}

MCPServer interface for MCP server operations (local server)

type MCPServerFuncs added in v0.8.0

type MCPServerFuncs struct {
	ListToolsFunc func() []mcp.MCPTool
	CallToolFunc  func(ctx context.Context, name string, args map[string]any) (*mcp.ToolResponse, error)
}

MCPServerFuncs allows creating a simple MCPServer from functions

func (*MCPServerFuncs) CallTool added in v0.8.0

func (m *MCPServerFuncs) CallTool(ctx context.Context, name string, args map[string]any) (*mcp.ToolResponse, error)

func (*MCPServerFuncs) ListTools added in v0.8.0

func (m *MCPServerFuncs) ListTools() []mcp.MCPTool

func (*MCPServerFuncs) ListToolsWithContext added in v0.9.0

func (m *MCPServerFuncs) ListToolsWithContext(ctx context.Context) []mcp.MCPTool

type MaxToolIterationsError added in v0.4.0

type MaxToolIterationsError struct {
	Iterations int
}

MaxToolIterationsError is returned when the maximum number of tool call iterations is reached without completing the conversation.

func NewMaxToolIterationsError added in v0.4.0

func NewMaxToolIterationsError(iterations int) *MaxToolIterationsError

NewMaxToolIterationsError creates a new MaxToolIterationsError.

func (*MaxToolIterationsError) Error added in v0.4.0

func (e *MaxToolIterationsError) Error() string

type Message

type Message struct {
	Role       string     `json:"role,omitempty"`
	Content    any        `json:"content,omitempty"`
	Refusal    string     `json:"refusal,omitempty"`
	ToolCalls  []ToolCall `json:"tool_calls,omitempty"`
	ToolCallID string     `json:"tool_call_id,omitempty"`
}

Message represents a chat message

func BuildAssistantMessage added in v0.4.0

func BuildAssistantMessage(content string) Message

BuildAssistantMessage creates an assistant message with the given content.

func BuildAssistantToolCallMessage added in v0.4.0

func BuildAssistantToolCallMessage(content string, toolCalls []ToolCall) Message

BuildAssistantToolCallMessage creates an assistant message with tool calls. This is useful when reconstructing a conversation that included tool calls.

func BuildMultimodalMessage added in v0.4.0

func BuildMultimodalMessage(parts ...ContentPart) Message

BuildMultimodalMessage creates a user message with multiple content parts.

func BuildSystemMessage added in v0.4.0

func BuildSystemMessage(content string) Message

BuildSystemMessage creates a system message with the given content.

func BuildToolResultMessage added in v0.4.0

func BuildToolResultMessage(toolCallID string, result string) Message

BuildToolResultMessage creates a tool result message for the given tool call ID.

func BuildUserMessage added in v0.4.0

func BuildUserMessage(content string) Message

BuildUserMessage creates a user message with the given content.

func ExecuteToolCall added in v0.4.0

func ExecuteToolCall(tc ToolCall, executor ToolExecutor) (Message, error)

ExecuteToolCall executes a single tool call using the provided executor. Returns a Message with the tool result that can be appended to the conversation.

func ExecuteToolCalls added in v0.4.0

func ExecuteToolCalls(toolCalls []ToolCall, executor ToolExecutor, stopOnError bool) ([]Message, error)

ExecuteToolCalls executes multiple tool calls using the provided executor and returns messages containing the results. If a tool call fails, the error message is included in the result and the execution continues (unless stopOnError is true).

func (*Message) GetContentAsString

func (m *Message) GetContentAsString() string

GetContentAsString returns the content as a string, handling both string and array formats

func (*Message) SetContentAsString

func (m *Message) SetContentAsString(content string)

SetContentAsString sets the content as a string

type Model

type Model struct {
	ID      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`
	OwnedBy string `json:"owned_by"`
}

Model represents an individual model

type ModelsResponse

type ModelsResponse struct {
	Object string  `json:"object"`
	Data   []Model `json:"data"`
}

ModelsResponse represents the response from the /models endpoint

type NoOpToolHandler

type NoOpToolHandler struct{}

NoOpToolHandler is a ToolHandler that does nothing. Useful as a default or for testing.

func (NoOpToolHandler) OnToolCall

func (NoOpToolHandler) OnToolCall(toolCall ToolCall) error

func (NoOpToolHandler) OnToolResult

func (NoOpToolHandler) OnToolResult(toolCallID, toolName, result string) error

type PromptTokensDetails

type PromptTokensDetails struct {
	CachedTokens int `json:"cached_tokens"`
	AudioTokens  int `json:"audio_tokens"`
}

PromptTokensDetails represents detailed prompt token usage

type RemoteServerConfig added in v0.8.0

type RemoteServerConfig struct {
	BaseURL   string
	Auth      mcp.AuthProvider
	Namespace string
	HTTPPool  pool.HTTPPool // Optional custom HTTP pool for this remote server
}

RemoteServerConfig holds configuration for a remote MCP server

type ResponseInputItemsResponse added in v0.6.9

type ResponseInputItemsResponse struct {
	Object string `json:"object"` // "list"
	Data   []any  `json:"data"`
}

ResponseInputItemsResponse represents a list of input items for a response

type ResponseInputTokensResponse added in v0.6.9

type ResponseInputTokensResponse struct {
	Object string        `json:"object"` // "list"
	Data   []TokenDetail `json:"data"`
}

ResponseInputTokensResponse represents token details for input

type ResponseListResponse added in v0.6.9

type ResponseListResponse struct {
	Object string           `json:"object"` // "list"
	Data   []ResponseObject `json:"data"`
}

ResponseListResponse represents a list of response objects

type ResponseObject added in v0.6.9

type ResponseObject struct {
	ID                 string                 `json:"id"`
	Object             string                 `json:"object"` // "response"
	CreatedAt          int64                  `json:"created_at"`
	Status             string                 `json:"status"` // "completed", "in_progress", "failed", "cancelled", "queued", "incomplete"
	Error              *APIError              `json:"error,omitempty"`
	IncompleteDetails  map[string]interface{} `json:"incomplete_details,omitempty"`
	Instructions       string                 `json:"instructions,omitempty"`
	MaxOutputTokens    *int                   `json:"max_output_tokens,omitempty"`
	Model              string                 `json:"model"`
	Output             []interface{}          `json:"output,omitempty"`
	ParallelToolCalls  *bool                  `json:"parallel_tool_calls,omitempty"`
	PreviousResponseID string                 `json:"previous_response_id,omitempty"`
	Reasoning          map[string]interface{} `json:"reasoning,omitempty"`
	Store              *bool                  `json:"store,omitempty"`
	Temperature        *float64               `json:"temperature,omitempty"`
	Text               map[string]interface{} `json:"text,omitempty"`
	ToolChoice         interface{}            `json:"tool_choice,omitempty"`
	Tools              []Tool                 `json:"tools,omitempty"`
	TopP               *float64               `json:"top_p,omitempty"`
	Truncation         string                 `json:"truncation,omitempty"`
	Usage              *Usage                 `json:"usage,omitempty"`
	Metadata           map[string]interface{} `json:"metadata,omitempty"`
}

ResponseObject represents a complete OpenAI Responses API response object https://platform.openai.com/docs/api-reference/responses/object

type SSEEventWriter added in v0.5.0

type SSEEventWriter interface {
	// WriteEvent writes an SSE comment event (prefixed with ":")
	// The event type and data are formatted as ":eventType:jsonData\n\n"
	WriteEvent(eventType string, data any) error
}

SSEEventWriter is an interface for writing SSE events. This allows integration with various HTTP frameworks' streaming implementations.

type SSEToolHandler added in v0.5.0

type SSEToolHandler struct {
	// contains filtered or unexported fields
}

SSEToolHandler implements ToolHandler to send tool events via SSE streaming. It wraps an SSEEventWriter and sends tool_start/tool_end events as SSE comments.

Usage pattern:

  1. Call OnToolCall() BEFORE executing the tool (sends tool_start with "running" status)
  2. Execute the tool
  3. Call OnToolResult() AFTER execution completes (sends tool_end with "complete" status and result)

Example SSE output:

:tool_start:{"tool_call_id":"call_abc123","tool_name":"search","status":"running"}

:tool_end:{"tool_call_id":"call_abc123","tool_name":"search","status":"complete","result":"..."}

func NewSSEToolHandler added in v0.5.0

func NewSSEToolHandler(writer SSEEventWriter, errorLogger func(err error, eventType, toolName string)) *SSEToolHandler

NewSSEToolHandler creates a new SSEToolHandler that sends tool events to the given writer. The optional errorLogger is called when write failures occur (errors are logged but not returned since tool events are just status notifications and shouldn't block tool execution).

func (*SSEToolHandler) OnToolCall added in v0.5.0

func (h *SSEToolHandler) OnToolCall(toolCall ToolCall) error

OnToolCall sends a tool_start event when a tool execution begins. This should be called BEFORE executing the tool. Write failures are logged but not returned as errors since they're just status notifications.

func (*SSEToolHandler) OnToolResult added in v0.5.0

func (h *SSEToolHandler) OnToolResult(toolCallID, toolName, result string) error

OnToolResult sends a tool_end event when a tool execution completes. This should be called AFTER the tool has finished executing. The result parameter contains the tool's output, which is included in the event so clients can display tool results in the UI. Write failures are logged but not returned as errors since they're just status notifications.

type SimpleSSEWriter added in v0.5.0

type SimpleSSEWriter struct {
	// contains filtered or unexported fields
}

SimpleSSEWriter is a basic implementation of SSEEventWriter that writes to an io.Writer. For production use, you may want to implement your own SSEEventWriter with proper flushing, error handling, and client disconnect detection.

func NewSimpleSSEWriter added in v0.5.0

func NewSimpleSSEWriter(w io.Writer, flusher func()) *SimpleSSEWriter

NewSimpleSSEWriter creates a SimpleSSEWriter that writes to the given io.Writer. If the writer implements http.Flusher, pass a flush function to flush after each write.

func (*SimpleSSEWriter) WriteEvent added in v0.5.0

func (s *SimpleSSEWriter) WriteEvent(eventType string, data any) error

WriteEvent writes an SSE comment event in the format ":eventType:jsonData\n\n"

type StreamError added in v0.4.0

type StreamError struct {
	Err error
}

StreamError is returned when an error occurs during streaming.

func NewStreamError added in v0.4.0

func NewStreamError(err error) *StreamError

NewStreamError creates a new StreamError.

func (*StreamError) Error added in v0.4.0

func (e *StreamError) Error() string

func (*StreamError) Unwrap added in v0.4.0

func (e *StreamError) Unwrap() error

type StreamingToolCallAccumulator added in v0.4.0

type StreamingToolCallAccumulator struct {
	// contains filtered or unexported fields
}

StreamingToolCallAccumulator handles the complex task of accumulating streaming tool call deltas into complete ToolCall objects. It buffers arguments that come in chunks, generates IDs when missing, and parses the final JSON arguments.

Usage:

acc := NewStreamingToolCallAccumulator()
for each streaming chunk {
    acc.ProcessDelta(chunk.Choices[0].Delta)
}
toolCalls := acc.Finalize()

func NewStreamingToolCallAccumulator added in v0.4.0

func NewStreamingToolCallAccumulator() *StreamingToolCallAccumulator

NewStreamingToolCallAccumulator creates a new accumulator for streaming tool calls.

func (*StreamingToolCallAccumulator) Count added in v0.4.0

func (acc *StreamingToolCallAccumulator) Count() int

Count returns the number of tool calls being accumulated.

func (*StreamingToolCallAccumulator) Finalize added in v0.4.0

func (acc *StreamingToolCallAccumulator) Finalize() []ToolCall

Finalize parses accumulated arguments and returns complete ToolCall objects. Tool calls with empty names are skipped. Returns tool calls sorted by index.

func (*StreamingToolCallAccumulator) GetToolCall added in v0.4.0

func (acc *StreamingToolCallAccumulator) GetToolCall(index int) *ToolCall

GetToolCall returns a specific tool call by index without finalizing. Returns nil if the index doesn't exist.

func (*StreamingToolCallAccumulator) HasToolCalls added in v0.4.0

func (acc *StreamingToolCallAccumulator) HasToolCalls() bool

HasToolCalls returns true if any tool calls are being accumulated.

func (*StreamingToolCallAccumulator) ProcessDelta added in v0.4.0

func (acc *StreamingToolCallAccumulator) ProcessDelta(delta Delta) []string

ProcessDelta processes a streaming delta and accumulates tool call data. Returns the list of tool call IDs that were updated (useful for tracking progress).

func (*StreamingToolCallAccumulator) ProcessDeltaWithIDCallback added in v0.4.0

func (acc *StreamingToolCallAccumulator) ProcessDeltaWithIDCallback(delta Delta, onNewID func(index int, id string)) []string

ProcessDeltaWithIDCallback processes a streaming delta and calls the callback with any newly generated tool call IDs. This is useful when you need to update the original delta with generated IDs for forwarding to clients.

func (*StreamingToolCallAccumulator) Reset added in v0.4.0

func (acc *StreamingToolCallAccumulator) Reset()

Reset clears the accumulator for reuse.

type TokenCounter added in v0.5.0

type TokenCounter struct {
	// contains filtered or unexported fields
}

TokenCounter estimates token usage for OpenAI API requests and responses. It provides a fast, reproducible approximation of token counts when exact counts are not available from the API.

func NewTokenCounter added in v0.5.0

func NewTokenCounter() *TokenCounter

NewTokenCounter creates a new TokenCounter

func (*TokenCounter) AddCompletionTokensFromDelta added in v0.5.0

func (tc *TokenCounter) AddCompletionTokensFromDelta(delta *Delta)

AddCompletionTokensFromDelta adds estimated completion tokens from a streaming delta

func (*TokenCounter) AddCompletionTokensFromMessage added in v0.5.0

func (tc *TokenCounter) AddCompletionTokensFromMessage(msg *Message)

AddCompletionTokensFromMessage adds estimated completion tokens from a chat message

func (*TokenCounter) AddCompletionTokensFromText added in v0.5.0

func (tc *TokenCounter) AddCompletionTokensFromText(text string)

AddCompletionTokensFromText adds estimated completion tokens from text

func (*TokenCounter) AddPromptTokensFromMessages added in v0.5.0

func (tc *TokenCounter) AddPromptTokensFromMessages(messages []Message)

AddPromptTokensFromMessages estimates and adds prompt tokens from chat messages

func (*TokenCounter) AddPromptTokensFromText added in v0.5.0

func (tc *TokenCounter) AddPromptTokensFromText(text string)

AddPromptTokensFromText adds estimated prompt tokens from text

func (*TokenCounter) GetUsage added in v0.5.0

func (tc *TokenCounter) GetUsage() Usage

GetUsage returns the current usage statistics

func (*TokenCounter) InjectUsageIfMissing added in v0.5.0

func (tc *TokenCounter) InjectUsageIfMissing(resp *ChatCompletionResponse)

InjectUsageIfMissing injects estimated usage into a chat completion response if it's missing or zero

func (*TokenCounter) Reset added in v0.5.0

func (tc *TokenCounter) Reset()

Reset resets the token counters to zero

type TokenDetail added in v0.6.9

type TokenDetail struct {
	Text        string  `json:"text"`
	Token       int     `json:"token"`
	Logprob     float64 `json:"logprob"`
	TopLogprobs []struct {
		Token   string  `json:"token"`
		Logprob float64 `json:"logprob"`
	} `json:"top_logprobs,omitempty"`
}

TokenDetail represents detailed information about a token

type Tool

type Tool struct {
	Type     string       `json:"type"`
	Function ToolFunction `json:"function"`
}

Tool represents an OpenAI tool definition

func MCPToolsToOpenAI

func MCPToolsToOpenAI(tools []mcp.MCPTool) []Tool

MCPToolsToOpenAI converts MCP tools to OpenAI function calling format

func MCPToolsToOpenAIFiltered

func MCPToolsToOpenAIFiltered(tools []mcp.MCPTool, filter func(name string) bool) []Tool

MCPToolsToOpenAIFiltered converts MCP tools to OpenAI format with optional filtering. If filter is nil, all tools are included. Otherwise, only tools where filter(name) returns true are included.

func NewTool added in v0.4.0

func NewTool(name, description string, parameters map[string]any) Tool

NewTool creates a tool definition for a function. The parameters should be a JSON Schema object describing the function parameters.

type ToolCall

type ToolCall struct {
	Index    int              `json:"index,omitempty"`
	ID       string           `json:"id"`
	Type     string           `json:"type"`
	Function ToolCallFunction `json:"function"`
}

ToolCall represents a tool call from the assistant

type ToolCallFunction

type ToolCallFunction struct {
	Name      string         `json:"name"`
	Arguments map[string]any `json:"arguments"`
}

ToolCallFunction represents the function details of a tool call

func (ToolCallFunction) MarshalJSON

func (tcf ToolCallFunction) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshaling for ToolCallFunction. OpenAI expects arguments as a JSON string, not an object.

func (*ToolCallFunction) UnmarshalJSON

func (tcf *ToolCallFunction) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for ToolCallFunction. OpenAI sends arguments as a JSON string, not an object.

type ToolExecutionError added in v0.4.0

type ToolExecutionError struct {
	ToolName string
	ToolID   string
	Err      error
}

ToolExecutionError is returned when a tool call fails.

func NewToolExecutionError added in v0.4.0

func NewToolExecutionError(toolName, toolID string, err error) *ToolExecutionError

NewToolExecutionError creates a new ToolExecutionError.

func (*ToolExecutionError) Error added in v0.4.0

func (e *ToolExecutionError) Error() string

func (*ToolExecutionError) Unwrap added in v0.4.0

func (e *ToolExecutionError) Unwrap() error

type ToolExecutor added in v0.4.0

type ToolExecutor func(name string, arguments map[string]any) (string, error)

ToolExecutor is a function that executes tool calls and returns the result. The function receives the tool name and arguments (as a map) and returns the result string and any error.

type ToolFilter

type ToolFilter func(name string) bool

ToolFilter is a function type for filtering tools by name

func AllTools

func AllTools() ToolFilter

AllTools returns a filter that includes all tools

func ExcludeTools

func ExcludeTools(names ...string) ToolFilter

ExcludeTools returns a filter that excludes tools with the specified names

func ToolsByName

func ToolsByName(names ...string) ToolFilter

ToolsByName returns a filter that includes only tools with the specified names

type ToolFunction

type ToolFunction struct {
	Name        string         `json:"name"`
	Description string         `json:"description"`
	Parameters  map[string]any `json:"parameters,omitempty"`
}

ToolFunction represents a function definition for a tool

type ToolHandler

type ToolHandler interface {
	// OnToolCall is called when a tool call is about to be executed.
	OnToolCall(toolCall ToolCall) error

	// OnToolResult is called when a tool call has completed.
	OnToolResult(toolCallID, toolName, result string) error
}

ToolHandler receives events during tool processing. Implement this interface to receive notifications when tools are called and when results are received.

func ToolHandlerFromContext

func ToolHandlerFromContext(ctx context.Context) ToolHandler

ToolHandlerFromContext retrieves a ToolHandler from the context. Returns nil if no handler is attached.

type ToolStatusEvent added in v0.5.0

type ToolStatusEvent struct {
	ToolCallID string         `json:"tool_call_id"`
	ToolName   string         `json:"tool_name"`
	Status     string         `json:"status"` // "running" or "complete"
	Arguments  map[string]any `json:"arguments,omitempty"`
	Result     string         `json:"result,omitempty"`
	Error      string         `json:"error,omitempty"`
}

ToolStatusEvent represents a tool execution status for SSE streaming. This is sent as an SSE comment (prefixed with ":") so standard SSE clients ignore it, but custom clients can parse it to show tool execution progress.

type UpdateConversationRequest added in v0.6.11

type UpdateConversationRequest struct {
	Metadata map[string]interface{} `json:"metadata"`
}

UpdateConversationRequest represents a request to update a conversation

type Usage

type Usage struct {
	PromptTokens            int                      `json:"prompt_tokens"`
	CompletionTokens        int                      `json:"completion_tokens"`
	TotalTokens             int                      `json:"total_tokens"`
	PromptTokensDetails     *PromptTokensDetails     `json:"prompt_tokens_details,omitempty"`
	CompletionTokensDetails *CompletionTokensDetails `json:"completion_tokens_details,omitempty"`
}

Usage represents token usage

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL