Help us shape the future of Go! Take the 2026 Go Developer Survey

ai

package module
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 28 Imported by: 3

Documentation

Index

Constants

View Source
const (
	// DefaultMaxRetries is how many times a failed request is retried when
	// StreamOptions.MaxRetries is nil. It matches the OpenAI SDKs' default.
	DefaultMaxRetries = 2
	// DefaultTimeout is how long a request waits for its response to start when
	// StreamOptions.TimeoutMs is nil. It matches the OpenAI Node SDK's default.
	DefaultTimeout = 10 * time.Minute
	// DefaultMaxRetriesDelay is the longest server-requested retry delay waited
	// out when StreamOptions.MaxRetriesDelayMs is nil.
	DefaultMaxRetriesDelay = 60 * time.Second
)
View Source
const NonVisionToolImagePlaceholder = "(tool image omitted: model does not support images)"
View Source
const NonVisionUserImagePlaceholder = "(image omitted: model does not support images)"

Variables

View Source
var Models = map[Provider]map[string]Model[API]{
	ProviderOpenAI: {
		"gpt-4": {
			ID:        "gpt-4",
			Name:      "GPT-4",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text"},
			Cost: Cost{
				Input:      decimal.MustParse("30"),
				Output:     decimal.MustParse("60"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 8192,
			MaxTokens:     8192,
		},
		"gpt-4-turbo": {
			ID:        "gpt-4-turbo",
			Name:      "GPT-4 Turbo",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("10"),
				Output:     decimal.MustParse("30"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     4096,
		},
		"gpt-4.1": {
			ID:        "gpt-4.1",
			Name:      "GPT-4.1",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2"),
				Output:     decimal.MustParse("8"),
				CacheRead:  decimal.MustParse("0.5"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 1047576,
			MaxTokens:     32768,
		},
		"gpt-4.1-mini": {
			ID:        "gpt-4.1-mini",
			Name:      "GPT-4.1 mini",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.4"),
				Output:     decimal.MustParse("1.6"),
				CacheRead:  decimal.MustParse("0.1"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 1047576,
			MaxTokens:     32768,
		},
		"gpt-4.1-nano": {
			ID:        "gpt-4.1-nano",
			Name:      "GPT-4.1 nano",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.1"),
				Output:     decimal.MustParse("0.4"),
				CacheRead:  decimal.MustParse("0.025"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 1047576,
			MaxTokens:     32768,
		},
		"gpt-4o": {
			ID:        "gpt-4o",
			Name:      "GPT-4o",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2.5"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("1.25"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-4o-2024-05-13": {
			ID:        "gpt-4o-2024-05-13",
			Name:      "GPT-4o (2024-05-13)",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("5"),
				Output:     decimal.MustParse("15"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     4096,
		},
		"gpt-4o-2024-08-06": {
			ID:        "gpt-4o-2024-08-06",
			Name:      "GPT-4o (2024-08-06)",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2.5"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("1.25"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-4o-2024-11-20": {
			ID:        "gpt-4o-2024-11-20",
			Name:      "GPT-4o (2024-11-20)",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2.5"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("1.25"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-4o-mini": {
			ID:        "gpt-4o-mini",
			Name:      "GPT-4o mini",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.15"),
				Output:     decimal.MustParse("0.6"),
				CacheRead:  decimal.MustParse("0.075"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-5": {
			ID:        "gpt-5",
			Name:      "GPT-5",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.25"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("0.125"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5-chat-latest": {
			ID:        "gpt-5-chat-latest",
			Name:      "GPT-5 Chat Latest",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.25"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("0.125"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-5-mini": {
			ID:        "gpt-5-mini",
			Name:      "GPT-5 Mini",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.25"),
				Output:     decimal.MustParse("2"),
				CacheRead:  decimal.MustParse("0.025"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5-nano": {
			ID:        "gpt-5-nano",
			Name:      "GPT-5 Nano",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.05"),
				Output:     decimal.MustParse("0.4"),
				CacheRead:  decimal.MustParse("0.005"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5-pro": {
			ID:        "gpt-5-pro",
			Name:      "GPT-5 Pro",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("15"),
				Output:     decimal.MustParse("120"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     272000,
		},
		"gpt-5.1": {
			ID:        "gpt-5.1",
			Name:      "GPT-5.1",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.25"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("0.125"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.1-codex": {
			ID:        "gpt-5.1-codex",
			Name:      "GPT-5.1 Codex",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.25"),
				Output:     decimal.MustParse("5"),
				CacheRead:  decimal.MustParse("0.125"),
				CacheWrite: decimal.MustParse("1.25"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.1-codex-max": {
			ID:        "gpt-5.1-codex-max",
			Name:      "GPT-5.1 Codex Max",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.25"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("0.125"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.2": {
			ID:        "gpt-5.2",
			Name:      "GPT-5.2",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.75"),
				Output:     decimal.MustParse("14"),
				CacheRead:  decimal.MustParse("0.175"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.2-chat-latest": {
			ID:        "gpt-5.2-chat-latest",
			Name:      "GPT-5.2 Chat",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.75"),
				Output:     decimal.MustParse("14"),
				CacheRead:  decimal.MustParse("0.175"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-5.2-pro": {
			ID:        "gpt-5.2-pro",
			Name:      "GPT-5.2 Pro",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("21"),
				Output:     decimal.MustParse("168"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.3-chat-latest": {
			ID:        "gpt-5.3-chat-latest",
			Name:      "GPT-5.3 Chat (latest)",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: false,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.75"),
				Output:     decimal.MustParse("14"),
				CacheRead:  decimal.MustParse("0.175"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     16384,
		},
		"gpt-5.3-codex": {
			ID:        "gpt-5.3-codex",
			Name:      "GPT-5.3 Codex",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.75"),
				Output:     decimal.MustParse("14"),
				CacheRead:  decimal.MustParse("0.175"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.3-codex-spark": {
			ID:        "gpt-5.3-codex-spark",
			Name:      "GPT-5.3 Codex Spark",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.75"),
				Output:     decimal.MustParse("14"),
				CacheRead:  decimal.MustParse("0.175"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     32000,
		},
		"gpt-5.4": {
			ID:        "gpt-5.4",
			Name:      "GPT-5.4",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2.5"),
				Output:     decimal.MustParse("15"),
				CacheRead:  decimal.MustParse("0.25"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 272000,
			MaxTokens:     128000,
		},
		"gpt-5.4-mini": {
			ID:        "gpt-5.4-mini",
			Name:      "GPT-5.4 mini",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.75"),
				Output:     decimal.MustParse("4.5"),
				CacheRead:  decimal.MustParse("0.075"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.4-nano": {
			ID:        "gpt-5.4-nano",
			Name:      "GPT-5.4 nano",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.2"),
				Output:     decimal.MustParse("1.25"),
				CacheRead:  decimal.MustParse("0.02"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-5.4-pro": {
			ID:        "gpt-5.4-pro",
			Name:      "GPT-5.4 Pro",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("30"),
				Output:     decimal.MustParse("180"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-5.5": {
			ID:        "gpt-5.5",
			Name:      "GPT-5.5",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("5"),
				Output:     decimal.MustParse("30"),
				CacheRead:  decimal.MustParse("0.5"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 272000,
			MaxTokens:     128000,
		},
		"gpt-5.5-pro": {
			ID:        "gpt-5.5-pro",
			Name:      "GPT-5.5 Pro",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff:   nil,
				ThinkingLevelXHigh: modelThinkingLevel("xhigh"),
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("30"),
				Output:     decimal.MustParse("180"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-5.6": {
			ID:        "gpt-5.6",
			Name:      "GPT-5.6",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("4"),
				Output:     decimal.MustParse("20"),
				CacheRead:  decimal.MustParse("0.4"),
				CacheWrite: decimal.MustParse("5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-5.6-luna": {
			ID:        "gpt-5.6-luna",
			Name:      "GPT-5.6 Luna",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.2"),
				Output:     decimal.MustParse("1.2"),
				CacheRead:  decimal.MustParse("0.02"),
				CacheWrite: decimal.MustParse("0.25"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-5.6-sol": {
			ID:        "gpt-5.6-sol",
			Name:      "GPT-5.6 Sol",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("4"),
				Output:     decimal.MustParse("20"),
				CacheRead:  decimal.MustParse("0.4"),
				CacheWrite: decimal.MustParse("5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-5.6-terra": {
			ID:        "gpt-5.6-terra",
			Name:      "GPT-5.6 Terra",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			ThinkingLevelMap: ThinkingLevelMap{
				ThinkingLevelOff: nil,
			},
			Input: []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2"),
				Output:     decimal.MustParse("12"),
				CacheRead:  decimal.MustParse("0.2"),
				CacheWrite: decimal.MustParse("2.5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-6-astra": {
			ID:        "gpt-6-astra",
			Name:      "GPT-6 Astra",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("10"),
				Output:     decimal.MustParse("50"),
				CacheRead:  decimal.MustParse("1"),
				CacheWrite: decimal.MustParse("12.5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-6-luna": {
			ID:        "gpt-6-luna",
			Name:      "GPT-6 Luna",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("0.1"),
				Output:     decimal.MustParse("0.5"),
				CacheRead:  decimal.MustParse("0.01"),
				CacheWrite: decimal.MustParse("0.125"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-6-sol": {
			ID:        "gpt-6-sol",
			Name:      "GPT-6 Sol",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("0.2"),
				CacheWrite: decimal.MustParse("2.5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-6.1-sol": {
			ID:        "gpt-6.1-sol",
			Name:      "GPT-6.1 Sol",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2"),
				Output:     decimal.MustParse("10"),
				CacheRead:  decimal.MustParse("0.1"),
				CacheWrite: decimal.MustParse("2.5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-daybreak-blue-latest": {
			ID:        "gpt-daybreak-blue-latest",
			Name:      "Daybreak Blue",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("4"),
				Output:     decimal.MustParse("20"),
				CacheRead:  decimal.MustParse("0.4"),
				CacheWrite: decimal.MustParse("5"),
			},
			ContextWindow: 1050000,
			MaxTokens:     128000,
		},
		"gpt-daybreak-red-latest": {
			ID:        "gpt-daybreak-red-latest",
			Name:      "Daybreak Red",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("12.5"),
				Output:     decimal.MustParse("75"),
				CacheRead:  decimal.MustParse("1.25"),
				CacheWrite: decimal.MustParse("15.625"),
			},
			ContextWindow: 400000,
			MaxTokens:     128000,
		},
		"gpt-realtime-2.1": {
			ID:        "gpt-realtime-2.1",
			Name:      "GPT-Realtime-2.1",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("4"),
				Output:     decimal.MustParse("24"),
				CacheRead:  decimal.MustParse("0.4"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 128000,
			MaxTokens:     32000,
		},
		"o1": {
			ID:        "o1",
			Name:      "o1",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("15"),
				Output:     decimal.MustParse("60"),
				CacheRead:  decimal.MustParse("7.5"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 200000,
			MaxTokens:     100000,
		},
		"o1-pro": {
			ID:        "o1-pro",
			Name:      "o1-pro",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("150"),
				Output:     decimal.MustParse("600"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 200000,
			MaxTokens:     100000,
		},
		"o3": {
			ID:        "o3",
			Name:      "o3",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("2"),
				Output:     decimal.MustParse("8"),
				CacheRead:  decimal.MustParse("0.5"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 200000,
			MaxTokens:     100000,
		},
		"o3-mini": {
			ID:        "o3-mini",
			Name:      "o3-mini",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text"},
			Cost: Cost{
				Input:      decimal.MustParse("1.1"),
				Output:     decimal.MustParse("4.4"),
				CacheRead:  decimal.MustParse("0.55"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 200000,
			MaxTokens:     100000,
		},
		"o3-pro": {
			ID:        "o3-pro",
			Name:      "o3-pro",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("20"),
				Output:     decimal.MustParse("80"),
				CacheRead:  decimal.MustParse("0"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 200000,
			MaxTokens:     100000,
		},
		"o4-mini": {
			ID:        "o4-mini",
			Name:      "o4-mini",
			API:       APIOpenAIResponses,
			Provider:  ProviderOpenAI,
			BaseURL:   "https://api.openai.com/v1",
			Reasoning: true,
			Input:     []string{"text", "image"},
			Cost: Cost{
				Input:      decimal.MustParse("1.1"),
				Output:     decimal.MustParse("4.4"),
				CacheRead:  decimal.MustParse("0.275"),
				CacheWrite: decimal.MustParse("0"),
			},
			ContextWindow: 200000,
			MaxTokens:     100000,
		},
	},
}
View Source
var OpenAIToolCallProviders = map[Provider]struct{}{
	ProviderOpenAI: {},
}

Functions

func BuildOpenAIResponsesParams

func BuildOpenAIResponsesParams(
	model Model[API],
	modelContext ModelContext,
	options *OpenAIResponseOptions,
) (responses.ResponseNewParams, error)

func CleanupSessionResources

func CleanupSessionResources(sessionID *string) error

func ClearApiProviders

func ClearApiProviders()

func ConvertResponsesMessages

func ConvertResponsesMessages(model Model[API], modelContext ModelContext, providers map[Provider]struct{}, options ConvertResponseMessagesOptions) (responses.ResponseInputParam, error)

func ConvertResponsesTools

func ConvertResponsesTools(
	tools []*Tool,
	options *ConvertResponsesToolsOptions,
) ([]responses.ToolUnionParam, error)

func CreateOpenAIResponsesClient

func CreateOpenAIResponsesClient(
	model Model[API],
	modelContext ModelContext,
	apiKey *string,
	optionHeaders *map[string]string,
	sessionID *string,
) (responses.ResponseService, error)

CreateOpenAIResponsesClient returns a Responses client configured only from its arguments. Unlike openai.NewClient, it reads no environment variables, so a server's OPENAI_BASE_URL, OPENAI_ORG_ID or OPENAI_PROJECT_ID cannot leak into a request made with a user's key.

func DefaultProviderAuth added in v0.6.0

func DefaultProviderAuth() map[Provider]ProviderAuth

DefaultProviderAuth returns the auth of the built-in providers. Each call returns a new map, so callers may change it.

func EncodeTextSignatureV1

func EncodeTextSignatureV1(id string, phase *TextSignaturePhase) string

func IsContextOverflow added in v0.3.0

func IsContextOverflow(message AssistantMessage, contextWindow int) bool

IsContextOverflow reports whether message indicates that the input exceeded the model's context window. It recognizes known provider errors, successful stops with Input + CacheRead greater than contextWindow, and length stops with zero output and Input + CacheRead filling at least 99% of contextWindow.

A non-positive contextWindow disables usage-based checks, but not error matching. Rate-limit, throttling, and service-unavailable errors are not context overflow. Silent input truncation without one of these signals cannot be detected.

func MergeHeaders added in v0.6.0

func MergeHeaders(layers ...map[string]string) map[string]string

MergeHeaders merges header maps into a new map. Later maps win, and names compare case-insensitively, so "authorization" replaces "Authorization". The winning spelling is kept. It returns nil when there are no headers.

func ModelsAreEqual

func ModelsAreEqual[TApi API](a *Model[TApi], b *Model[TApi]) bool

func RegisterApiProvider

func RegisterApiProvider[TApi API](provider ApiProvider[TApi, StreamOptions], sourceID *string)

func RegisterSessionResourceCleanup

func RegisterSessionResourceCleanup(cleanup SessionResourceCleanup) func()

func UnregisterApiProvider

func UnregisterApiProvider(sourceID string)

func ValidateToolArguments

func ValidateToolArguments(tool Tool, toolCall ToolCall) (any, error)

ValidateToolArguments validates tool call arguments against the tool's JSON schema.

func ValidateToolCall

func ValidateToolCall(tools []*Tool, toolCall ToolCall) (any, error)

ValidateToolCall finds a tool by name and validates the tool call arguments against its schema.

Types

type API

type API string
const (
	APIOpenAIResponses API = "openai-responses"
)

func (API) IsKnown

func (a API) IsKnown() bool

type APIKeyAuth added in v0.6.0

type APIKeyAuth struct {
	// Name is shown to the user, such as "OpenAI API key".
	Name string
	// Login asks the user for a key and returns the credential to store. Nil
	// means the provider only uses ambient auth.
	Login func(ctx context.Context, in AuthInteraction) (*Credential, error)
	// Check optionally reports whether auth is configured without request-time
	// work. Set it when Resolve runs commands or makes network calls; without
	// it, checks call Resolve.
	Check func(ctx context.Context, env AuthContext, cred *Credential) (*AuthCheck, error)
	// Resolve builds request auth from cred, which may be nil, and env. It
	// returns nil, nil when the provider is not configured.
	Resolve func(ctx context.Context, env AuthContext, cred *Credential) (*AuthResult, error)
}

APIKeyAuth is API key auth: a stored key or provider config, plus ambient sources such as environment variables.

func EnvAPIKeyAuth added in v0.6.0

func EnvAPIKeyAuth(name string, envVars ...string) *APIKeyAuth

EnvAPIKeyAuth is standard API key auth: a stored key wins, otherwise the first of envVars that is set. Login asks for the key. Providers that resolve differently, such as from provider config, credential files or IAM, write their own APIKeyAuth.

type ApiProvider

type ApiProvider[TApi API, TOptions any] struct {
	Api          TApi
	Stream       StreamFunction[TApi, TOptions]
	StreamSimple StreamFunction[TApi, SimpleStreamOptions]
}

type ApiProviderInternal

type ApiProviderInternal struct {
	Api          API
	Stream       ApiStreamFunction
	StreamSimple ApiStreamSimpleFunction
}

func GetApiProvider

func GetApiProvider(api API) (ApiProviderInternal, bool)

func GetApiProviders

func GetApiProviders() []ApiProviderInternal

func ResolveAPIProvider

func ResolveAPIProvider(api API) (ApiProviderInternal, error)

type ApiStreamFunction

type ApiStreamFunction func(
	Model Model[API],
	ModelContext ModelContext,
	Options *StreamOptions,
) (*AssistantMessageEventStream, error)

type ApiStreamSimpleFunction

type ApiStreamSimpleFunction func(
	model Model[API],
	ModelContext ModelContext,
	options *SimpleStreamOptions,
) (*AssistantMessageEventStream, error)

type AssistantContent

type AssistantContent interface {
	// contains filtered or unexported methods
}

type AssistantMessage

type AssistantMessage struct {
	Role          Role                         `json:"role"`
	Content       []AssistantContent           `json:"content"`
	Api           API                          `json:"api"`
	Provider      Provider                     `json:"provider"`
	Model         string                       `json:"model"`
	ResponseModel *string                      `json:"responseModel,omitempty"`
	ResponseID    *string                      `json:"responseId,omitempty"`
	Diagnostics   []AssistantMessageDiagnostic `json:"diagnostics,omitempty"`
	Usage         Usage                        `json:"usage"`
	StopReason    StopReason                   `json:"stopReason"`
	ErrorMessage  string                       `json:"errorMessage,omitempty"`
	Timestamp     int64                        `json:"timestamp"` // Unix timestamp in milliseconds
}

func Complete

func Complete(model Model[API], modelContext ModelContext, options *StreamOptions) (AssistantMessage, error)

func CompleteSimple

func CompleteSimple(model Model[API], modelContext ModelContext, options *SimpleStreamOptions) (AssistantMessage, error)

func (AssistantMessage) AgentMessageType

func (AssistantMessage) AgentMessageType() string

type AssistantMessageDiagnostic

type AssistantMessageDiagnostic struct {
	Type      string               `json:"type"`
	Timestamp int64                `json:"timestamp"`
	Error     *DiagnosticErrorInfo `json:"error,omitempty"`
	Details   any                  `json:"details,omitempty"`
}

type AssistantMessageEvent

type AssistantMessageEvent interface {
	EventType() string
}

type AssistantMessageEventStream

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

func NewAssistantMessageEventStream

func NewAssistantMessageEventStream(buffer int) *AssistantMessageEventStream

func Stream

func Stream(model Model[API], modelContext ModelContext, options *StreamOptions) (*AssistantMessageEventStream, error)

func StreamOpenAIResponse

func StreamOpenAIResponse(ctx context.Context, model Model[API], modelContext ModelContext, options *OpenAIResponseOptions) (*AssistantMessageEventStream, error)

func StreamOpenAIResponses added in v0.2.0

func StreamOpenAIResponses(model Model[API], modelContext ModelContext, options *StreamOptions) (*AssistantMessageEventStream, error)

func StreamSimple

func StreamSimple(model Model[API], modelContext ModelContext, options *SimpleStreamOptions) (*AssistantMessageEventStream, error)

func StreamSimpleOpenAIResponses

func StreamSimpleOpenAIResponses(model Model[API], modelContext ModelContext, options *SimpleStreamOptions) (*AssistantMessageEventStream, error)

StreamSimpleOpenAIResponses streams a response. It never reads the environment: the API key comes from options.ApiKey, which callers resolve with ResolveProviderAuth and apply with ApplyModelAuth.

func (*AssistantMessageEventStream) End

func (s *AssistantMessageEventStream) End(err error)

func (*AssistantMessageEventStream) Events

func (*AssistantMessageEventStream) Push

func (*AssistantMessageEventStream) Result

type AssistantMessageEventType

type AssistantMessageEventType string
const (
	AssistantMessageEventText  AssistantMessageEventType = "text"
	AssistantMessageEventDone  AssistantMessageEventType = "done"
	AssistantMessageEventError AssistantMessageEventType = "error"
)

type AuthCheck added in v0.6.0

type AuthCheck struct {
	Type   CredentialType
	Source string
}

AuthCheck reports that a provider has auth configured, found without refreshing tokens or doing other request-time work.

func CheckProviderAuth added in v0.6.0

func CheckProviderAuth(
	ctx context.Context,
	provider Provider,
	auth ProviderAuth,
	store CredentialStore,
	env AuthContext,
) (*AuthCheck, error)

CheckProviderAuth reports whether provider has auth configured, and from where, without refreshing tokens. It returns nil, nil when the provider is not configured. Use it for status UI and model lists; requests use ResolveProviderAuth.

It follows ResolveProviderAuth's precedence: a stored OAuth credential counts as configured even when expired, and a stored credential whose type has no handler in auth means unconfigured. API key auth is checked with auth.APIKey.Check when set, otherwise by resolving it. A nil env means no ambient auth.

type AuthContext added in v0.6.0

type AuthContext interface {
	// Env returns the named variable, and false when it is unset or blank.
	Env(name string) (string, bool)
	// FileExists reports whether path exists. A leading ~ is the user's home
	// directory.
	FileExists(path string) bool
}

AuthContext is where ambient auth comes from: environment variables and credential files. It is injectable so that multi-tenant apps can turn ambient auth off with NoAmbientAuth.

func DefaultAuthContext added in v0.6.0

func DefaultAuthContext() AuthContext

DefaultAuthContext reads the process environment and file system.

func NoAmbientAuth added in v0.6.0

func NoAmbientAuth() AuthContext

NoAmbientAuth is an AuthContext with no variables and no files, so only stored credentials and overrides configure a provider.

type AuthError added in v0.6.0

type AuthError struct {
	Code     AuthErrorCode
	Provider Provider
	Message  string
	Err      error
}

AuthError is returned when auth resolution fails, as pi's ModelsError is.

func (*AuthError) Error added in v0.6.0

func (e *AuthError) Error() string

func (*AuthError) Unwrap added in v0.6.0

func (e *AuthError) Unwrap() error

type AuthErrorCode added in v0.6.0

type AuthErrorCode string

AuthErrorCode says which part of auth resolution failed.

const (
	// AuthErrorStore means the credential store or API key resolution failed.
	// Retrying may succeed.
	AuthErrorStore AuthErrorCode = "auth"
	// AuthErrorOAuth means an OAuth refresh failed. The stored credential is
	// kept, but the user likely has to log in again.
	AuthErrorOAuth AuthErrorCode = "oauth"
)

type AuthEvent added in v0.6.0

type AuthEvent struct {
	Type    AuthEventType
	Message string
}

AuthEvent tells the user about login progress. It needs no answer.

type AuthEventType added in v0.6.0

type AuthEventType string

AuthEventType is the kind of an AuthEvent.

const (
	AuthEventInfo     AuthEventType = "info"
	AuthEventProgress AuthEventType = "progress"
)

type AuthInteraction added in v0.6.0

type AuthInteraction struct {
	// Prompt returns the entered text, or the chosen option's ID for a select
	// prompt. It returns an error if the user cancels or ctx is done.
	Prompt func(ctx context.Context, prompt AuthPrompt) (string, error)
	// Notify shows event to the user. It may be nil.
	Notify func(event AuthEvent)
}

AuthInteraction is how a login flow talks to the user, for both API key and OAuth logins. The app provides it: a TUI prompts in the terminal, a web app renders a form.

type AuthPrompt added in v0.6.0

type AuthPrompt struct {
	Type        AuthPromptType
	Message     string
	Placeholder string
	// Options are the choices of a select prompt.
	Options []AuthPromptOption
}

AuthPrompt asks the user for input during login.

type AuthPromptOption added in v0.6.0

type AuthPromptOption struct {
	ID          string
	Label       string
	Description string
}

AuthPromptOption is one choice of a select prompt.

type AuthPromptType added in v0.6.0

type AuthPromptType string

AuthPromptType is the kind of input an AuthPrompt asks for.

const (
	AuthPromptText   AuthPromptType = "text"
	AuthPromptSecret AuthPromptType = "secret"
	AuthPromptSelect AuthPromptType = "select"
)

type AuthResolutionOverrides added in v0.6.0

type AuthResolutionOverrides struct {
	// APIKey replaces stored and ambient auth when set, even to "".
	APIKey *string
	// Env is laid over the ambient environment and a stored credential's Env.
	Env map[string]string
	// MinOAuthValidity, when longer than the default five minutes, is how long
	// an OAuth token must stay valid; a refresh that leaves less is an error.
	MinOAuthValidity time.Duration
}

AuthResolutionOverrides changes how ResolveProviderAuth resolves one request.

type AuthResult added in v0.6.0

type AuthResult struct {
	Auth ModelAuth
	// Env holds provider-scoped config resolved from the credential and
	// ambient sources.
	Env map[string]string
	// Source labels where the auth came from for status UI, such as
	// "OPENAI_API_KEY" or "OAuth".
	Source string
}

AuthResult is resolved request auth for a provider.

func ResolveProviderAuth added in v0.6.0

func ResolveProviderAuth(
	ctx context.Context,
	provider Provider,
	auth ProviderAuth,
	store CredentialStore,
	env AuthContext,
	overrides *AuthResolutionOverrides,
) (*AuthResult, error)

ResolveProviderAuth resolves the request auth for provider. It returns nil, nil when the provider is not configured.

A stored credential owns the provider: env is consulted only when nothing is stored. There is no fallback to env after a failed refresh, or when the stored credential's type has no handler in auth, so a broken login never silently switches to an ambient key. The order is:

  1. overrides.APIKey, when auth has API key support
  2. a stored OAuth credential, refreshed when it expires within five minutes (or overrides.MinOAuthValidity, if longer)
  3. a stored API key credential
  4. ambient auth from env, such as environment variables

overrides.Env is laid over env and over a stored API key credential's Env. A nil env means no ambient auth.

type CacheRetention

type CacheRetention string
const (
	CacheRetentionNone  CacheRetention = "none"
	CacheRetentionShort CacheRetention = "short"
	CacheRetentionLong  CacheRetention = "long"
)

func ResolveCacheRetention

func ResolveCacheRetention(cacheRetention CacheRetention) CacheRetention

ResolveCacheRetention returns cacheRetention, or CacheRetentionShort when it is unset. CacheRetentionNone is kept, so callers can turn caching off.

type ContentType

type ContentType string
const (
	ContentTypeText     ContentType = "text"
	ContentTypeThinking ContentType = "thinking"
	ContentTypeImage    ContentType = "image"
	ContentTypeToolCall ContentType = "toolCall"
)

type ConvertResponseMessagesOptions

type ConvertResponseMessagesOptions struct {
	IncludeSystemPrompt *bool `json:"includeSystemPrompt,omitempty"`
}

type ConvertResponsesToolsOptions

type ConvertResponsesToolsOptions struct {
	Strict *bool
}

type Cost

type Cost struct {
	Input      decimal.Decimal
	Output     decimal.Decimal
	CacheRead  decimal.Decimal
	CacheWrite decimal.Decimal
	Total      decimal.Decimal
}

type Credential added in v0.6.0

type Credential struct {
	Type CredentialType
	// Key is the API key of an api_key credential.
	Key string
	// Env holds provider-scoped config of an api_key credential, such as an
	// account ID.
	Env map[string]string
	// OAuth is the token set of an oauth credential.
	OAuth *OAuthToken
}

Credential is one stored credential for a provider: an API key or an OAuth token set, as Type says.

func RefreshStoredOAuthCredential added in v0.6.0

func RefreshStoredOAuthCredential(
	ctx context.Context,
	store CredentialStore,
	provider Provider,
	oauth OAuthAuth,
	needsRefresh func(*Credential) bool,
) (*Credential, error)

RefreshStoredOAuthCredential refreshes provider's stored OAuth credential under the store's lock and stores the result before the lock is released. needsRefresh is checked again under the lock, so when several requests or processes find the token expired, only the first refreshes and the rest use its result.

ctx cancels only the wait for the lock. Once the refresh starts, the provider may already have rotated the refresh token, so the refresh and its write ignore ctx and are bounded by oauthRefreshTimeout; otherwise a cancelled caller could throw away the only valid refresh token. A caller cancelled during the refresh gets ctx.Err() at once while the refresh finishes in the background.

It returns the stored OAuth credential afterwards, or nil if the provider no longer has one, such as after a logout.

func (*Credential) Clone added in v0.6.0

func (c *Credential) Clone() *Credential

Clone returns a deep copy of c, so a store can hand out credentials without sharing its own. Clone of nil is nil.

type CredentialInfo added in v0.6.0

type CredentialInfo struct {
	Provider Provider
	Type     CredentialType
}

CredentialInfo is credential metadata for listing, without secrets.

type CredentialStore added in v0.6.0

type CredentialStore interface {
	Read(ctx context.Context, provider Provider) (*Credential, error)
	List(ctx context.Context) ([]CredentialInfo, error)
	Modify(ctx context.Context, provider Provider, fn func(current *Credential) (*Credential, error)) (*Credential, error)
	Delete(ctx context.Context, provider Provider) error
}

CredentialStore stores one credential per provider, for one user. Apps provide persistent stores; NewInMemoryCredentialStore is the default.

Modify is the only write path, so every change is a serialized read-modify-write. ResolveProviderAuth refreshes OAuth tokens inside Modify, so concurrent requests cannot refresh a rotated token twice.

  • Read returns nil, nil when nothing is stored. The credential may be expired; request auth comes from ResolveProviderAuth.
  • List returns metadata only. It must not resolve or expose secrets.
  • Modify runs fn with the current credential (nil if none) while holding a lock on the provider, across processes too where the backing store supports it. fn may make a network call; hold the lock across it. fn returning nil leaves the credential unchanged. Modify returns the credential after the write. An error from fn stores nothing and is returned, wrapped or not, so errors.As still finds it. If ctx is done before the lock is acquired, Modify returns ctx.Err() without running fn.
  • Delete removes the credential, serialized against Modify. Deleting nothing succeeds.

Methods return errors only when storage fails. Stores must not keep the credentials passed to them, nor return ones they keep; see Credential.Clone.

type CredentialType added in v0.6.0

type CredentialType string

CredentialType is the kind of a stored credential.

const (
	CredentialAPIKey CredentialType = "api_key"
	CredentialOAuth  CredentialType = "oauth"
)

type DiagnosticErrorInfo

type DiagnosticErrorInfo struct {
	Name    *string `json:"name,omitempty"`
	Message string  `json:"message"`
	Stack   *string `json:"stack,omitempty"`
	Code    any     `json:"code,omitempty"`
}

type DoneEvent

type DoneEvent struct {
	Type    string           `json:"type"`
	Reason  StopReason       `json:"reason"`
	Message AssistantMessage `json:"message"`
}

func (DoneEvent) EventType

func (DoneEvent) EventType() string

type ErrorEvent

type ErrorEvent struct {
	Type    string           `json:"type"`
	Reason  StopReason       `json:"reason"`
	Message AssistantMessage `json:"message"`
}

func (ErrorEvent) EventType

func (ErrorEvent) EventType() string

type EventStream

type EventStream[T any, R any] struct {
	// contains filtered or unexported fields
}

func NewEventStream

func NewEventStream[T any, R any](
	buffer int,
	isComplete func(T) bool,
	extractResult func(T) R,
) *EventStream[T, R]

func (*EventStream[T, R]) End

func (s *EventStream[T, R]) End(result R)

func (*EventStream[T, R]) Events

func (s *EventStream[T, R]) Events() <-chan T

func (*EventStream[T, R]) Push

func (s *EventStream[T, R]) Push(event T)

func (*EventStream[T, R]) Result

func (s *EventStream[T, R]) Result() R

type ImageContent

type ImageContent struct {
	Type     ContentType `json:"type"`
	Image    string      `json:"image"`
	MimeType string      `json:"mimeType"`
}

type InMemoryCredentialStore added in v0.6.0

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

InMemoryCredentialStore is a CredentialStore that keeps credentials in memory, for tests and apps that do not persist auth. Modify and Delete are serialized per provider, within this process only.

func NewInMemoryCredentialStore added in v0.6.0

func NewInMemoryCredentialStore() *InMemoryCredentialStore

NewInMemoryCredentialStore returns an empty InMemoryCredentialStore.

func (*InMemoryCredentialStore) Delete added in v0.6.0

func (s *InMemoryCredentialStore) Delete(ctx context.Context, provider Provider) error

func (*InMemoryCredentialStore) List added in v0.6.0

func (*InMemoryCredentialStore) Modify added in v0.6.0

func (s *InMemoryCredentialStore) Modify(ctx context.Context, provider Provider, fn func(current *Credential) (*Credential, error)) (*Credential, error)

func (*InMemoryCredentialStore) Read added in v0.6.0

func (s *InMemoryCredentialStore) Read(ctx context.Context, provider Provider) (*Credential, error)

type Message

type Message interface {
	// contains filtered or unexported methods
}

func TransformMessages

func TransformMessages(messages []Message, model Model[API], allowedToolCallProviders map[Provider]struct{}) []Message

type Model

type Model[tApi API] struct {
	ID               string                 `json:"id"`
	Name             string                 `json:"name"`
	API              tApi                   `json:"api"`
	Provider         Provider               `json:"provider"`
	BaseURL          string                 `json:"baseUrl"`
	Reasoning        bool                   `json:"reasoning"`
	ThinkingLevelMap ThinkingLevelMap       `json:"thinkingLevelMap"`
	Input            []string               `json:"input"`
	Cost             Cost                   `json:"cost"` // $/million tokens
	ContextWindow    int                    `json:"contextWindow"`
	MaxTokens        int                    `json:"maxTokens"`
	Headers          *map[string]string     `json:"headers"`
	Compat           *OpenAIResponsesCompat `json:"compat"`
}

func ApplyModelAuth added in v0.6.0

func ApplyModelAuth[T API](model Model[T], options *StreamOptions, auth ModelAuth) Model[T]

ApplyModelAuth applies auth to a request: it sets options.ApiKey, lays auth.Headers under options.Headers, and returns model with auth.BaseURL. The caller's headers win, so an app can still override a header per request. It changes neither the caller's header map nor model's.

func GetModel

func GetModel(provider Provider, modelID string) (Model[API], bool)

func GetModels

func GetModels(provider Provider) []Model[API]

type ModelAuth added in v0.6.0

type ModelAuth struct {
	APIKey  *string
	Headers map[string]string
	BaseURL *string
}

ModelAuth is the auth for a single model request. Anything that cannot be expressed as an API key, headers, or a base URL is provider config, not auth.

type ModelContext

type ModelContext struct {
	SystemPrompt *string   `json:"systemPrompt,omitempty"`
	Messages     []Message `json:"messages,omitempty"`
	Tools        []*Tool   `json:"tools,omitempty"`
}

type ModelThinkingLevel

type ModelThinkingLevel string
const (
	ThinkingLevelOff     ModelThinkingLevel = "off"
	ThinkingLevelMinimal ModelThinkingLevel = "minimal"
	ThinkingLevelLow     ModelThinkingLevel = "low"
	ThinkingLevelMedium  ModelThinkingLevel = "medium"
	ThinkingLevelHigh    ModelThinkingLevel = "high"
	ThinkingLevelXHigh   ModelThinkingLevel = "xhigh"
)

func ClampThinkingLevel

func ClampThinkingLevel[TApi API](model Model[TApi], level ModelThinkingLevel) ModelThinkingLevel

func GetSupportedThinkingLevels

func GetSupportedThinkingLevels[TApi API](model Model[TApi]) []ModelThinkingLevel

type OAuthAuth added in v0.6.0

type OAuthAuth struct {
	// Name is shown to the user, such as "OpenAI (ChatGPT subscription)".
	Name string
	// IsSubscription reports whether access is backed by a provider
	// subscription rather than API billing.
	IsSubscription bool
	// Login runs the provider's login flow and returns the credential to store.
	Login func(ctx context.Context, in AuthInteraction) (*Credential, error)
	// Refresh exchanges cred's refresh token over the network. It runs under
	// the store's lock with its own timeout. It must return the complete new
	// credential, keeping the old refresh token if the provider sent none.
	Refresh func(ctx context.Context, cred *Credential) (*Credential, error)
	// ToAuth derives request auth from a valid credential, including a base
	// URL or headers specific to the credential. It must have no side effects.
	ToAuth func(cred *Credential) (ModelAuth, error)
}

OAuthAuth is OAuth auth. Refresh and ToAuth are separate so that ResolveProviderAuth can refresh under the store's lock: Refresh produces a credential, and ToAuth derives request auth from whichever credential ends up stored.

type OAuthToken added in v0.6.0

type OAuthToken struct {
	Access  string
	Refresh string
	Expires time.Time
	// Extra keeps provider fields, such as the Codex account ID, through a
	// round trip.
	Extra map[string]json.RawMessage
}

OAuthToken is the token set of an OAuth credential.

type OpenAIResponseOptions

type OpenAIResponseOptions struct {
	StreamOptions
	ReasoningEffort  *string `json:"reasoningEffort,omitempty"`
	ReasoningSummary *string `json:"reasoningSummary,omitempty"`
	ServiceTier      *string `json:"serviceTier,omitempty"`
}

type OpenAIResponsesCompat

type OpenAIResponsesCompat struct {
	SendSessionIdHeader        *bool `json:"send_session_id_header,omitempty"`
	SupportsLongCacheRetention *bool `json:"supports_long_cache_retention,omitempty"`
}

type ParsedTextSignature

type ParsedTextSignature struct {
	ID    string
	Phase *TextSignaturePhase
}

func ParseTextSignature

func ParseTextSignature(signature *string) *ParsedTextSignature

type Provider

type Provider string
const (
	ProviderOpenAI Provider = "openai"
)

func GetProviders

func GetProviders() []Provider

func (Provider) IsKnown

func (p Provider) IsKnown() bool

type ProviderAuth added in v0.6.0

type ProviderAuth struct {
	APIKey *APIKeyAuth
	OAuth  *OAuthAuth
}

ProviderAuth is how a provider authenticates. At least one of APIKey and OAuth is set; even providers that only use ambient auth or no key at all have APIKey auth, whose Resolve reports whether they are configured.

type ProviderResponse

type ProviderResponse struct {
	Status  int               `json:"status"`
	Headers map[string]string `json:"headers"`
}

type RegisteredApiProvider

type RegisteredApiProvider struct {
	Provider ApiProviderInternal
	SourceID *string
}

type ResolvedOpenAIResponsesCompat

type ResolvedOpenAIResponsesCompat struct {
	SendSessionIDHeader        bool
	SupportsLongCacheRetention bool
}

type Role

type Role string
const (
	RoleUser       Role = "user"
	RoleAssistant  Role = "assistant"
	RoleToolResult Role = "toolResult"
)

type SessionResourceCleanup

type SessionResourceCleanup func(SessionID *string) error

type SimpleStreamOptions

type SimpleStreamOptions struct {
	StreamOptions
	Reasoning       *ModelThinkingLevel
	ThinkingBudgets *ThinkingBudgets
}

type StartEvent

type StartEvent struct {
	Type    string           `json:"type"`
	Partial AssistantMessage `json:"partial"`
}

func (StartEvent) EventType

func (StartEvent) EventType() string

type StopReason

type StopReason string
const (
	StopReasonStop    StopReason = "stop"
	StopReasonLength  StopReason = "length"
	StopReasonToolUse StopReason = "toolUse"
	StopReasonError   StopReason = "error"
	StopReasonAborted StopReason = "aborted"
)

func MapOpenAIResponseStopReason

func MapOpenAIResponseStopReason(status responses.ResponseStatus) (StopReason, error)

type StreamFunction

type StreamFunction[TApi API, TOptions any] func(
	model Model[TApi],
	ModelContext ModelContext,
	options *TOptions,
) (*AssistantMessageEventStream, error)

type StreamOptions

type StreamOptions struct {
	Temperature       *decimal.Decimal                                        `json:"temperature,omitempty"`
	MaxTokens         *int64                                                  `json:"max_tokens,omitempty"`
	Signal            context.Context                                         `json:"signal,omitempty"`
	ApiKey            *string                                                 `json:"api_key,omitempty"`
	Transport         *Transport                                              `json:"transport,omitempty"`
	Cache             *CacheRetention                                         `json:"cache,omitempty"`
	SessionId         *string                                                 `json:"session_id,omitempty"`
	OnPayload         func(payload any, model Model[API]) (any, error)        `json:"on_payload,omitempty"`
	OnResponse        func(response ProviderResponse, model Model[API]) error `json:"on_response,omitempty"`
	Headers           map[string]string                                       `json:"headers,omitempty"`
	TimeoutMs         *int64                                                  `json:"timeout_ms,omitempty"`
	MaxRetries        *int64                                                  `json:"max_retries,omitempty"`
	MaxRetriesDelayMs *int64                                                  `json:"max_retries_delay_ms,omitempty"`
	HTTPClient        *http.Client                                            `json:"-"`
	Metadata          map[string]any                                          `json:"metadata,omitempty"`
}

StreamOptions configures one model request.

TimeoutMs bounds how long each attempt waits for the response to start; it does not limit a stream that has started. Nil means DefaultTimeout (10 minutes). MaxRetries is how many times a failed request is retried; nil means DefaultMaxRetries (2). MaxRetriesDelayMs fails a request at once, instead of retrying, when the server asks for a longer retry delay. Nil means DefaultMaxRetriesDelay (60 seconds). Zero TimeoutMs or MaxRetriesDelayMs means no limit. Negative values are an error, as are durations over about 292 years, the most a time.Duration can hold.

type TextContent

type TextContent struct {
	Type          ContentType `json:"type"`
	Text          string      `json:"text"`
	TextSignature *string     `json:"textSignature,omitempty"`
}

type TextDeltaEvent

type TextDeltaEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Delta        string           `json:"delta"`
	Partial      AssistantMessage `json:"partial"`
}

func (TextDeltaEvent) EventType

func (TextDeltaEvent) EventType() string

type TextEndEvent

type TextEndEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Content      string           `json:"content"`
	Partial      AssistantMessage `json:"partial"`
}

func (TextEndEvent) EventType

func (TextEndEvent) EventType() string

type TextSignaturePhase

type TextSignaturePhase string
const (
	PhaseCommentary  TextSignaturePhase = "commentary"
	PhaseFinalAnswer TextSignaturePhase = "final_answer"
)

type TextStartEvent

type TextStartEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Partial      AssistantMessage `json:"partial"`
}

func (TextStartEvent) EventType

func (TextStartEvent) EventType() string

type ThinkingBudgets

type ThinkingBudgets struct {
	Minimal *int64 `json:"minimal,omitempty"`
	Low     *int64 `json:"low,omitempty"`
	Medium  *int64 `json:"medium,omitempty"`
	High    *int64 `json:"high,omitempty"`
}

type ThinkingContent

type ThinkingContent struct {
	Type              ContentType `json:"type"`
	Thinking          string      `json:"thinking"`
	ThinkingSignature *string     `json:"thinkingSignature,omitempty"`
	Redacted          *bool       `json:"redacted,omitempty"`
}

type ThinkingDeltaEvent

type ThinkingDeltaEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Delta        string           `json:"delta"`
	Partial      AssistantMessage `json:"partial"`
}

func (ThinkingDeltaEvent) EventType

func (ThinkingDeltaEvent) EventType() string

type ThinkingEndEvent

type ThinkingEndEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Content      string           `json:"content"`
	Partial      AssistantMessage `json:"partial"`
}

func (ThinkingEndEvent) EventType

func (ThinkingEndEvent) EventType() string

type ThinkingLevelMap

type ThinkingLevelMap map[ModelThinkingLevel]*string

type ThinkingStartEvent

type ThinkingStartEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Partial      AssistantMessage `json:"partial"`
}

func (ThinkingStartEvent) EventType

func (ThinkingStartEvent) EventType() string

type Tool

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

type ToolCall

type ToolCall struct {
	Type             ContentType `json:"type"`
	Id               string      `json:"id"`
	Name             string      `json:"name"`
	Args             any         `json:"args"`
	ThoughtSignature *string     `json:"thoughtSignature,omitempty"`
	PartialJson      *string     `json:"partialJson,omitempty"`
}

type ToolCallDeltaEvent

type ToolCallDeltaEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Delta        string           `json:"delta"`
	Partial      AssistantMessage `json:"partial"`
}

func (ToolCallDeltaEvent) EventType

func (ToolCallDeltaEvent) EventType() string

type ToolCallEndEvent

type ToolCallEndEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	ToolCall     ToolCall         `json:"toolCall"`
	Partial      AssistantMessage `json:"partial"`
}

func (ToolCallEndEvent) EventType

func (ToolCallEndEvent) EventType() string

type ToolCallStartEvent

type ToolCallStartEvent struct {
	Type         string           `json:"type"`
	ContentIndex int64            `json:"contentIndex"`
	Partial      AssistantMessage `json:"partial"`
}

func (ToolCallStartEvent) EventType

func (ToolCallStartEvent) EventType() string

type ToolResultContent

type ToolResultContent interface {
	// contains filtered or unexported methods
}

func ReplaceToolResultImagesWithPlaceholder

func ReplaceToolResultImagesWithPlaceholder(content []ToolResultContent, placeholder string) []ToolResultContent

type ToolResultMessage

type ToolResultMessage struct {
	Role       Role                `json:"role"`
	ToolCallID string              `json:"toolCallId"`
	ToolName   string              `json:"toolName"`
	Content    []ToolResultContent `json:"content"`
	Details    any                 `json:"details,omitempty"`
	IsError    bool                `json:"isError"`
	Timestamp  int64               `json:"timestamp"` // Unix timestamp in milliseconds
}

func (ToolResultMessage) AgentMessageType

func (ToolResultMessage) AgentMessageType() string

type Transport

type Transport string
const (
	TransportSSE             Transport = "sse"
	TransportWebsocket       Transport = "websocket"
	TransportWebsocketCached Transport = "websocket-cached"
	TransportAuto            Transport = "auto"
)

type Usage

type Usage struct {
	Input      int64
	Output     int64
	CacheRead  int64
	CacheWrite int64
	Total      int64
	Cost       Cost
}

func CalculateCost

func CalculateCost(model Model[API], usage Usage) (Usage, error)

type UserContent

type UserContent interface {
	// contains filtered or unexported methods
}

func ReplaceUserImagesWithPlaceholder

func ReplaceUserImagesWithPlaceholder(content []UserContent, placeholder string) []UserContent

type UserMessage

type UserMessage struct {
	Role      Role          `json:"role"`
	Content   []UserContent `json:"content"`
	Timestamp int64         `json:"timestamp"` // Unix timestamp in milliseconds
}

func (UserMessage) AgentMessageType

func (UserMessage) AgentMessageType() string

AgentMessageType returns the message type as a string for use in the agent loop.

Directories

Path Synopsis
Package providertest fakes model provider APIs in tests.
Package providertest fakes model provider APIs in tests.
openairesponses
Package openairesponses builds OpenAI Responses API fixtures for providertest servers.
Package openairesponses builds OpenAI Responses API fixtures for providertest servers.

Jump to

Keyboard shortcuts

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