provider

package
v0.13.4 Latest Latest
Warning

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

Go to latest
Published: Jul 1, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const EmbedModelID = "all-MiniLM-L6-v2"

EmbedModelID is the default model identifier returned by EmbedModel().

View Source
const LocalEmbedderProvider = "local"

LocalEmbedderProvider is the provider ID for the inbuilt, no-dependency embedder that runs a sentence-embedding model in-process. It needs no API key and no network access. It is the only embedder ogcode supports — agentic memory embeddings are always produced locally.

Variables

View Source
var AnthropicModels = []CatalogModel{

	{ID: "claude-opus-4-7", Name: "Claude Opus 4.7", ActiveByDefault: true, InputPricePerM: 15, OutputPricePerM: 75, SupportsImages: true},
	{ID: "claude-opus-4-6", Name: "Claude Opus 4.6", ActiveByDefault: true, InputPricePerM: 15, OutputPricePerM: 75, SupportsImages: true},
	{ID: "claude-sonnet-4-6", Name: "Claude Sonnet 4.6", ActiveByDefault: true, InputPricePerM: 3, OutputPricePerM: 15, SupportsImages: true},
	{ID: "claude-haiku-4-5-20251001", Name: "Claude Haiku 4.5", ActiveByDefault: true, InputPricePerM: 0.80, OutputPricePerM: 4, SupportsImages: true},

	{ID: "claude-opus-4-5-20251101", Name: "Claude Opus 4.5", ActiveByDefault: false, InputPricePerM: 15, OutputPricePerM: 75, SupportsImages: true},
	{ID: "claude-opus-4-1-20250805", Name: "Claude Opus 4.1", ActiveByDefault: false, InputPricePerM: 15, OutputPricePerM: 75, SupportsImages: true},
	{ID: "claude-sonnet-4-5-20250929", Name: "Claude Sonnet 4.5", ActiveByDefault: false, InputPricePerM: 3, OutputPricePerM: 15, SupportsImages: true},

	{ID: "claude-opus-4-20250514", Name: "Claude Opus 4", ActiveByDefault: false, InputPricePerM: 15, OutputPricePerM: 75, SupportsImages: true},
	{ID: "claude-sonnet-4-20250514", Name: "Claude Sonnet 4", ActiveByDefault: false, InputPricePerM: 3, OutputPricePerM: 15, SupportsImages: true},
}

AnthropicModels is the authoritative list of Anthropic models. Maintained by contributors — see file header for instructions. All listed Claude models are multimodal and accept image input.

View Source
var OpenAIModels = []CatalogModel{

	{ID: "gpt-5", Name: "GPT-5", ActiveByDefault: true, InputPricePerM: 10, OutputPricePerM: 30, SupportsImages: true},
	{ID: "gpt-5-mini", Name: "GPT-5 Mini", ActiveByDefault: true, InputPricePerM: 1.50, OutputPricePerM: 6, SupportsImages: true},
	{ID: "gpt-5-nano", Name: "GPT-5 Nano", ActiveByDefault: false, InputPricePerM: 0.10, OutputPricePerM: 0.40, SupportsImages: true},

	{ID: "gpt-4.1", Name: "GPT-4.1", ActiveByDefault: true, InputPricePerM: 2, OutputPricePerM: 8, SupportsImages: true},
	{ID: "gpt-4.1-mini", Name: "GPT-4.1 Mini", ActiveByDefault: true, InputPricePerM: 0.40, OutputPricePerM: 1.60, SupportsImages: true},
	{ID: "gpt-4.1-nano", Name: "GPT-4.1 Nano", ActiveByDefault: false, InputPricePerM: 0.10, OutputPricePerM: 0.40, SupportsImages: true},

	{ID: "gpt-4o", Name: "GPT-4o", ActiveByDefault: false, InputPricePerM: 2.50, OutputPricePerM: 10, SupportsImages: true},
	{ID: "gpt-4o-mini", Name: "GPT-4o Mini", ActiveByDefault: false, InputPricePerM: 0.15, OutputPricePerM: 0.60, SupportsImages: true},

	{ID: "o4-mini", Name: "o4 Mini", ActiveByDefault: true, InputPricePerM: 1.10, OutputPricePerM: 4.40, SupportsImages: true},
	{ID: "o3", Name: "o3", ActiveByDefault: true, InputPricePerM: 10, OutputPricePerM: 40, SupportsImages: true},
	{ID: "o3-mini", Name: "o3 Mini", ActiveByDefault: false, InputPricePerM: 1.10, OutputPricePerM: 4.40},
	{ID: "o1", Name: "o1", ActiveByDefault: false, InputPricePerM: 15, OutputPricePerM: 60, SupportsImages: true},
	{ID: "o1-mini", Name: "o1 Mini", ActiveByDefault: false, InputPricePerM: 1.50, OutputPricePerM: 6},
}

OpenAIModels is the authoritative list of OpenAI models. Maintained by contributors — see file header for instructions. SupportsImages marks multimodal models. The o*-mini reasoning models are text-only; the GPT-4o/4.1/5 families and o1/o3/o4-mini accept images.

View Source
var ProviderPriority = []string{"anthropic", "openai", "openrouter", "ollama"}

ProviderPriority is the stable order used to choose a default provider when a session does not specify a model.

Functions

func EnsureLocalEmbedderModel added in v0.11.0

func EnsureLocalEmbedderModel(ctx context.Context) error

EnsureLocalEmbedderModel performs a blocking preflight that guarantees the inbuilt local embedder's model weights are present on disk in the default cache directory. It downloads the ~86 MB ONNX file on first use; subsequent calls hit the cache and return immediately.

Call this once at server startup (before serving requests) so the one-time download completes up front, regardless of whether agentic memory is enabled at boot — the local embedder is the default and may be enabled at runtime via the settings UI without a restart. A non-nil error means the download could not complete (e.g. no network); the caller may continue, as the next Embed call will retry.

func ProbeImageSupport added in v0.6.0

func ProbeImageSupport(ctx context.Context, p Provider, modelID string) (supports bool, definitive bool, err error)

ProbeImageSupport sends a single minimal image to the model and reports whether it was accepted. Return values:

  • (true, true, nil): the model accepted the image and responded.
  • (false, true, nil): the provider rejected the request for an image/modality reason.
  • (false, false, err): inconclusive (network/auth/rate-limit/etc.) — do NOT cache; retry later.

func ValidateCredentials added in v0.10.0

func ValidateCredentials(ctx context.Context, providerID, apiKey, baseURL string) error

ValidateCredentials makes a minimal chat request with the given credentials to confirm the provider accepts them. It returns nil when the credentials work, or an error describing the failure. Used by the settings/onboarding "test key" flow. The caller is responsible for any timeout via ctx.

Types

type AnthropicProvider

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

AnthropicProvider implements Provider for the Anthropic Messages API.

func NewAnthropicProvider

func NewAnthropicProvider() *AnthropicProvider

func (*AnthropicProvider) ID

func (p *AnthropicProvider) ID() string

func (*AnthropicProvider) Models

func (p *AnthropicProvider) Models() []ModelInfo

func (*AnthropicProvider) StreamChat

func (p *AnthropicProvider) StreamChat(ctx context.Context, req StreamRequest) (<-chan StreamEvent, error)

type CatalogModel added in v0.2.3

type CatalogModel struct {
	ID              string
	Name            string
	ActiveByDefault bool
	InputPricePerM  float64 // USD per 1M input tokens (0 = unknown)
	OutputPricePerM float64 // USD per 1M output tokens (0 = unknown)
	SupportsImages  bool    // whether the model accepts image input
}

CatalogModel is a statically-known model for a provider that does not expose a live /v1/models discovery endpoint.

type ContentPart

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

type Embedder added in v0.2.1

type Embedder interface {
	// Embed returns embedding vectors for the given input strings.
	Embed(ctx context.Context, inputs []string) ([][]float32, error)
	EmbedModel() string
}

Embedder is an optional interface that providers can implement to support text embeddings (used for agentic memory semantic recall).

type LocalEmbedder added in v0.11.0

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

LocalEmbedder is a provider.Embedder implementation that runs a sentence-embedding model entirely in-process — no API key, no network call (after the one-time model download), no separate model server.

The small tokenizer/config assets are embedded in the binary (see internal/provider/embedmodel) and lazily materialized to a cache directory on first use. The large ONNX weight file (~86 MB) is downloaded from Hugging Face on first use rather than embedded, so the distributable binary stays small — mirroring ogcode's search-bridge download pattern.

It uses Hugot's pure-Go backend (GoMLX simplego), so the binary stays CGO-free and self-contained. The default model is sentence-transformers/all-MiniLM-L6-v2, producing 384-dim embeddings.

func NewLocalEmbedder added in v0.11.0

func NewLocalEmbedder(cacheDir string) *LocalEmbedder

NewLocalEmbedder creates a LocalEmbedder. cacheDir overrides the default materialization location (~/.ogcode/embed-model) when non-empty.

func (*LocalEmbedder) Close added in v0.11.0

func (e *LocalEmbedder) Close() error

Close releases the Hugot session and model resources. Safe to call multiple times.

func (*LocalEmbedder) Embed added in v0.11.0

func (e *LocalEmbedder) Embed(ctx context.Context, inputs []string) ([][]float32, error)

Embed returns embedding vectors for the given inputs. It lazily initializes the model on first call. Inference is serialized because the pure-Go GoMLX backend is not safe for concurrent use from multiple goroutines.

func (*LocalEmbedder) EmbedModel added in v0.11.0

func (e *LocalEmbedder) EmbedModel() string

EmbedModel returns the identifier of the model used for embeddings.

func (*LocalEmbedder) EnsureModelDownloaded added in v0.11.0

func (e *LocalEmbedder) EnsureModelDownloaded(ctx context.Context) error

EnsureModelDownloaded guarantees the local embedder's model weights are present on disk (downloading them on first use and verifying the SHA-256) but does NOT build the inference pipeline. It is meant for a startup preflight: call it once at server boot so the one-time ~86 MB download completes before the server accepts requests. A LocalEmbedder later used for inference (e.g. by agentic memory) shares the same cache directory, finds the cached model, and only pays the pipeline-build cost — never re-downloading.

It is idempotent: a sidecar marker records the verified hash so subsequent calls skip both the download and the full-file hash check, returning immediately. Safe to call concurrently with init/Embed on another instance sharing the same cache directory (file writes are idempotent and the final rename is atomic).

func (*LocalEmbedder) ID added in v0.11.0

func (e *LocalEmbedder) ID() string

ID returns the provider identifier.

func (*LocalEmbedder) Models added in v0.11.0

func (e *LocalEmbedder) Models() []ModelInfo

Models returns an empty model list: the local embedder is embedding-only and not selectable as a chat provider.

func (*LocalEmbedder) StreamChat added in v0.11.0

func (e *LocalEmbedder) StreamChat(ctx context.Context, req StreamRequest) (<-chan StreamEvent, error)

StreamChat is not supported — the local embedder is embedding-only.

type MessageImage added in v0.6.0

type MessageImage struct {
	MediaType string `json:"mediaType"`
	Data      string `json:"data"`
}

MessageImage is an image attached to a message, carried provider-neutrally. Data is base64-encoded image bytes; MediaType is e.g. "image/jpeg".

type ModelInfo

type ModelInfo struct {
	ID              string  `json:"id"`
	Name            string  `json:"name"`
	ProviderID      string  `json:"providerId"`
	Default         bool    `json:"default"`
	ActiveByDefault bool    `json:"activeByDefault"`
	InputPricePerM  float64 `json:"inputPricePerM"`
	OutputPricePerM float64 `json:"outputPricePerM"`
	SupportsImages  bool    `json:"supportsImages"`
}

type ModelMessage

type ModelMessage struct {
	Role       string          `json:"role"`
	Content    json.RawMessage `json:"content,omitempty"`
	ToolCalls  json.RawMessage `json:"tool_calls,omitempty"`
	ToolCallID string          `json:"tool_call_id,omitempty"`
	Name       string          `json:"name,omitempty"`
	// Images carries image attachments for a tool-result message. Providers
	// render these per their API: Anthropic embeds them in the tool_result
	// content block; OpenAI-family inject a follow-up user message.
	Images []MessageImage `json:"images,omitempty"`
}

type ModelRefresher added in v0.1.3

type ModelRefresher interface {
	RefreshModels()
}

ModelRefresher is an optional interface that providers can implement to support dynamic model list refreshing.

type OpenAIProvider

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

OpenAIProvider implements Provider for the OpenAI Chat Completions API. Also used for OpenRouter and Ollama (same API format, different base URL).

func NewEmbedProvider added in v0.2.1

func NewEmbedProvider(providerID, apiKey, model string) (*OpenAIProvider, error)

NewEmbedProvider creates an OpenAIProvider configured for embedding. providerID must be "openai", "openrouter", or "ollama". If apiKey is non-empty it overrides the env var key. If model is non-empty it is stored as the provider model (used for embedding). Deprecated: Use NewEmbedProviderWithConfig for full control over baseURL.

func NewEmbedProviderWithConfig added in v0.8.1

func NewEmbedProviderWithConfig(providerID, apiKey, model, baseURL string) (*OpenAIProvider, error)

NewEmbedProviderWithConfig creates an OpenAIProvider configured for embedding with optional apiKey, model, and baseURL overrides. Env-var values are used as the base; non-empty parameters override them.

func NewOllamaProvider

func NewOllamaProvider() *OpenAIProvider

NewOllamaProvider creates an OpenAI-compatible provider for Ollama. When OLLAMA_BASE_URL points to a cloud endpoint (not localhost), the model list is fetched dynamically from /v1/models. For local Ollama, a static fallback list is used.

func NewOpenAIProvider

func NewOpenAIProvider() *OpenAIProvider

func NewOpenRouterProvider

func NewOpenRouterProvider() *OpenAIProvider

NewOpenRouterProvider creates an OpenAI-compatible provider for OpenRouter.

func (*OpenAIProvider) Embed added in v0.2.1

func (p *OpenAIProvider) Embed(ctx context.Context, inputs []string) ([][]float32, error)

func (*OpenAIProvider) EmbedModel added in v0.2.1

func (p *OpenAIProvider) EmbedModel() string

func (*OpenAIProvider) ID

func (p *OpenAIProvider) ID() string

func (*OpenAIProvider) Models

func (p *OpenAIProvider) Models() []ModelInfo

func (*OpenAIProvider) RefreshModels added in v0.1.3

func (p *OpenAIProvider) RefreshModels()

RefreshModels clears the cached model list so the next call to Models() will re-fetch from the endpoint (for cloud providers). Not safe to call concurrently with Models().

func (*OpenAIProvider) StreamChat

func (p *OpenAIProvider) StreamChat(ctx context.Context, req StreamRequest) (<-chan StreamEvent, error)

type Provider

type Provider interface {
	ID() string
	Models() []ModelInfo
	StreamChat(ctx context.Context, req StreamRequest) (<-chan StreamEvent, error)
}

func NewEmbedder added in v0.11.0

func NewEmbedder() Provider

NewEmbedder returns the inbuilt local embedder. ogcode no longer supports third-party embedders (OpenAI, OpenRouter, Ollama) for agentic memory — the pure-Go all-MiniLM-L6-v2 model runs in-process with zero configuration. The returned provider also satisfies Embedder.

func NewProviderWithConfig added in v0.2.1

func NewProviderWithConfig(providerID, apiKey, baseURL string) (Provider, error)

NewProviderWithConfig creates a Provider with explicit credentials, used when credentials come from the DB rather than environment variables. providerID must be "anthropic", "openai", "openrouter", or "ollama". Env-var values are used as the base; apiKey and baseURL override them when non-empty.

type Registry

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

func NewRegistry

func NewRegistry() *Registry

func (*Registry) Default added in v0.10.0

func (r *Registry) Default() Provider

Default returns the highest-priority registered provider, or nil if the registry has no providers.

func (*Registry) Get

func (r *Registry) Get(id string) Provider

func (*Registry) List

func (r *Registry) List() []string

func (*Registry) ListModels

func (r *Registry) ListModels() []ModelInfo

func (*Registry) ModelSupportsImages added in v0.6.0

func (r *Registry) ModelSupportsImages(modelID string) bool

ModelSupportsImages reports whether the given model accepts image input. Unknown models default to false.

func (*Registry) RefreshModels added in v0.1.3

func (r *Registry) RefreshModels()

RefreshModels clears cached model lists for all providers that support it, forcing re-fetch on next Models() call.

func (*Registry) Register

func (r *Registry) Register(p Provider)

func (*Registry) RegisterCustomModel

func (r *Registry) RegisterCustomModel(modelID, providerID string)

func (*Registry) ReplaceProviders added in v0.10.0

func (r *Registry) ReplaceProviders(providers map[string]Provider)

ReplaceProviders atomically swaps the set of registered providers. Custom model routing (RegisterCustomModel) is preserved. Used to apply provider credential changes from the settings/onboarding UI without a server restart.

func (*Registry) ResolveProvider

func (r *Registry) ResolveProvider(modelID string) Provider

func (*Registry) UnregisterCustomModel

func (r *Registry) UnregisterCustomModel(modelID string)

type StreamEvent

type StreamEvent struct {
	Type         StreamEventType `json:"type"`
	Text         string          `json:"text,omitempty"`
	ToolCallID   string          `json:"toolCallId,omitempty"`
	ToolName     string          `json:"toolName,omitempty"`
	ToolInput    json.RawMessage `json:"toolInput,omitempty"`
	FinishReason *string         `json:"finishReason,omitempty"`
	Usage        *TokenUsage     `json:"usage,omitempty"`
	Error        string          `json:"error,omitempty"`
}

type StreamEventType

type StreamEventType string
const (
	EventTextDelta     StreamEventType = "text-delta"
	EventToolCallStart StreamEventType = "tool-call-start"
	EventToolCallDelta StreamEventType = "tool-call-delta"
	EventToolCallEnd   StreamEventType = "tool-call-end"
	EventReasoning     StreamEventType = "reasoning"
	EventFinish        StreamEventType = "finish"
	EventUsage         StreamEventType = "usage"
	EventError         StreamEventType = "error"
)

type StreamRequest

type StreamRequest struct {
	Model       string           `json:"model"`
	System      []string         `json:"system"`
	Messages    []ModelMessage   `json:"messages"`
	Tools       []ToolDefinition `json:"tools"`
	Temperature float64          `json:"temperature,omitempty"`
	MaxTokens   int              `json:"maxTokens,omitempty"`
	Abort       context.Context  `json:"-"`
}

type TokenUsage

type TokenUsage struct {
	InputTokens      int `json:"inputTokens,omitempty"`
	OutputTokens     int `json:"outputTokens,omitempty"`
	ReasoningTokens  int `json:"reasoningTokens,omitempty"`
	CacheReadTokens  int `json:"cacheReadTokens,omitempty"`
	CacheWriteTokens int `json:"cacheWriteTokens,omitempty"`
}

TokenUsage carries per-message token accounting from a provider. Fields are non-zero where the provider reports them.

type ToolDefinition

type ToolDefinition struct {
	Name        string          `json:"name"`
	Description string          `json:"description"`
	Parameters  json.RawMessage `json:"parameters"`
}

Directories

Path Synopsis
Package embedmodel bundles a sentence-embedding model so agentic memory works with zero external dependencies — no API key, no network call (after the one-time model download), no separate model server required.
Package embedmodel bundles a sentence-embedding model so agentic memory works with zero external dependencies — no API key, no network call (after the one-time model download), no separate model server required.

Jump to

Keyboard shortcuts

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