chore: add .agents and twilight ai skill

This commit is contained in:
Acbox
2026-03-18 15:48:16 +08:00
parent 3ca84a3ab6
commit 9c386c1ea5
3 changed files with 1013 additions and 0 deletions
+205
View File
@@ -0,0 +1,205 @@
---
name: twilight-ai
description: Assist with development in the Twilight AI Go SDK. Use when working in this repository, adding or updating providers, embeddings, tool calling, streaming, examples, or docs for Twilight AI.
---
# Twilight AI
## When To Use
Use this skill when the task involves `twilight-ai`, especially:
- implementing or refactoring SDK APIs in `sdk/`
- adding or updating providers under `provider/`
- working on `GenerateText`, `GenerateTextResult`, `StreamText`, `Embed`, or `EmbedMany`
- adding tool-calling, streaming, reasoning, or embedding support
- writing examples, docs, or usage guidance for this library
## Project Snapshot
Twilight AI is a lightweight Go AI SDK with a provider-agnostic core API.
- Text generation: `sdk.GenerateText`, `sdk.GenerateTextResult`, `sdk.StreamText`
- Embeddings: `sdk.Embed`, `sdk.EmbedMany`
- Tool calling: `sdk.Tool`, `sdk.NewTool[T]`, `WithMaxSteps`, approval flow
- Streaming: typed `StreamPart` events over Go channels
- Current providers:
- `provider/openai/completions`
- `provider/openai/responses`
- `provider/anthropic/messages`
- `provider/google/generativeai`
- `provider/openai/embedding`
- `provider/google/embedding`
## Default Mental Model
Prefer the high-level SDK API first, then drop to provider details only when needed.
- `sdk.Model` binds a chat model to a `sdk.Provider`
- `sdk.EmbeddingModel` binds an embedding model to an `sdk.EmbeddingProvider`
- The client orchestrates tool loops, callbacks, approvals, and streaming lifecycle
- Providers handle backend-specific HTTP, request mapping, response parsing, and SSE translation
## Core API Guidance
Choose the narrowest API that matches the task:
- Need only final text: use `sdk.GenerateText`
- Need usage, finish reason, steps, sources, files, or tool details: use `sdk.GenerateTextResult`
- Need live output: use `sdk.StreamText`
- Need one vector: use `sdk.Embed`
- Need multiple vectors or embedding token usage: use `sdk.EmbedMany`
If the task introduces examples or docs, prefer simple end-to-end snippets that start with:
1. construct provider
2. get model
3. call SDK API
4. handle error
## Provider Selection Rules
- Use `openai/completions` for broad OpenAI-compatible support such as DeepSeek, Groq, Ollama, Azure-style compatible endpoints, and generic `/chat/completions` backends.
- Use `openai/responses` when the task needs OpenAI Responses API features such as first-class reasoning models, reasoning summaries, URL citation annotations, or flat input mapping.
- Use `anthropic/messages` for Claude and Anthropic extended thinking via `WithThinking`.
- Use `google/generativeai` for Gemini chat, tool calling, vision, streaming, and Gemini reasoning.
- Use `openai/embedding` or `google/embedding` for embeddings. Keep embedding-provider work separate from chat-provider work.
## Implementation Rules
### Chat Providers
If adding or changing a chat provider, preserve the `sdk.Provider` contract:
- `Name()`
- `ListModels(ctx)`
- `Test(ctx)`
- `TestModel(ctx, modelID)`
- `DoGenerate(ctx, params)`
- `DoStream(ctx, params)`
Keep provider responsibilities focused:
- translate SDK messages/options into backend request format
- parse backend responses into `sdk.GenerateResult`
- map backend streaming events into typed `sdk.StreamPart` values
- report usage, finish reasons, reasoning, tool calls, sources, and files when supported
### Embedding Providers
Embedding providers are separate from chat providers. Use `sdk.EmbeddingProvider` and return an `sdk.EmbeddingModel` via `EmbeddingModel(id)`.
When updating embeddings:
- keep `sdk.Embed` for single-string convenience
- keep `sdk.EmbedMany` for batched requests
- preserve `Usage.Tokens`
- only expose dimensions/task-type behavior when the backend supports it
### Tool Calling
Prefer `sdk.NewTool[T]` for new tool examples and integrations. It gives typed input and inferred JSON Schema.
Use these defaults unless the task requires something else:
- `WithToolChoice("auto")` for normal use
- `WithMaxSteps(0)` for inspection-only tool calls
- `WithMaxSteps(N)` for automatic execution loops
- `RequireApproval: true` only for sensitive side effects
When streaming with tools, ensure the implementation can emit:
- tool input construction parts
- tool execution parts
- progress updates
- denial/error events when applicable
### Streaming
Twilight AI streaming is channel-first and type-safe. Prefer type switches over loosely typed event parsing.
Important expectations:
- `StreamText` returns `*sdk.StreamResult`
- `sr.Stream` must be consumed before relying on `sr.Steps` or `sr.Messages`
- `Text()` and `ToResult()` are the convenience paths when callers do not want manual event handling
### Messages And Results
Preserve the SDK message model and avoid backend-specific shapes leaking into public usage.
- user, assistant, system, and tool messages should stay in SDK types
- support rich parts where relevant: text, image, file, reasoning, tool call, tool result
- keep finish reason mapping aligned with SDK constants such as `stop`, `length`, `content-filter`, and `tool-calls`
## Common Task Patterns
### Add A New Usage Example
Use this structure:
1. pick the correct provider package
2. create provider with explicit options
3. create model via `ChatModel` or `EmbeddingModel`
4. call the top-level `sdk` function
5. show minimal but idiomatic result handling
### Add Or Update A Provider Feature
Check all affected layers:
1. request mapping
2. non-streaming response mapping
3. streaming event mapping
4. finish-reason and usage mapping
5. reasoning/tool/source/file support if the backend exposes them
6. model discovery and provider health checks if endpoints exist
### Add A Custom Provider
Use the built-in providers as the template. A custom provider should feel identical to existing ones from the caller's perspective.
Minimum behavior:
1. return a provider-bound model from `ChatModel`
2. implement discovery and health-check methods
3. support `DoGenerate`
4. support `DoStream` with correct lifecycle parts
## Documentation Rules
When writing Twilight AI docs or README content:
- prefer provider-agnostic phrasing first, provider-specific details second
- use Go examples, not pseudocode, unless explaining an interface contract
- keep examples small and runnable in spirit
- mention exact package paths for imports
- explain when to choose Completions vs Responses when OpenAI is involved
- keep embeddings, tool calling, and streaming as separate concerns unless the example truly combines them
## Terminology
Use these terms consistently:
- Provider: backend implementation for chat generation
- Embedding provider: backend implementation for embeddings
- Model: provider-bound chat model
- Embedding model: provider-bound embedding model
- Tool calling: model requests a tool invocation
- Multi-step execution: automatic tool loop controlled by `WithMaxSteps`
- Stream part: a typed event from `StreamText`
## Quick Checklist
Before finishing work in this repo, verify:
- the chosen provider package matches the intended backend capabilities
- chat and embedding concerns are not mixed accidentally
- public examples use top-level `sdk` APIs unless lower-level behavior is the point
- streaming logic uses typed `StreamPart` handling
- tool-calling changes cover both inspection mode and multi-step mode when relevant
- provider work includes health checks or model discovery behavior if the backend supports them
## Additional Resources
- For exported APIs, signatures, provider options, and stream/event types, see [reference.md](reference.md)
+798
View File
@@ -0,0 +1,798 @@
# Twilight AI API Reference
This file is the detailed API companion for `skill/SKILL.md`.
Use it when the task needs exact package names, exported types, function signatures, provider options, or stream/event shapes.
## Package Map
- `github.com/memohai/twilight-ai/sdk`
- `github.com/memohai/twilight-ai/provider/openai/completions`
- `github.com/memohai/twilight-ai/provider/openai/responses`
- `github.com/memohai/twilight-ai/provider/anthropic/messages`
- `github.com/memohai/twilight-ai/provider/google/generativeai`
- `github.com/memohai/twilight-ai/provider/openai/embedding`
- `github.com/memohai/twilight-ai/provider/google/embedding`
## Package `sdk`
### Client And Top-Level Helpers
```go
type Client struct{}
func NewClient() *Client
func (c *Client) GenerateText(ctx context.Context, options ...GenerateOption) (string, error)
func (c *Client) GenerateTextResult(ctx context.Context, options ...GenerateOption) (*GenerateResult, error)
func (c *Client) StreamText(ctx context.Context, options ...GenerateOption) (*StreamResult, error)
func (c *Client) Embed(ctx context.Context, value string, options ...EmbedOption) ([]float64, error)
func (c *Client) EmbedMany(ctx context.Context, values []string, options ...EmbedOption) (*EmbedResult, error)
func GenerateText(ctx context.Context, options ...GenerateOption) (string, error)
func GenerateTextResult(ctx context.Context, options ...GenerateOption) (*GenerateResult, error)
func StreamText(ctx context.Context, options ...GenerateOption) (*StreamResult, error)
func Embed(ctx context.Context, value string, options ...EmbedOption) ([]float64, error)
func EmbedMany(ctx context.Context, values []string, options ...EmbedOption) (*EmbedResult, error)
```
### Provider Contracts
```go
type Provider interface {
Name() string
ListModels(ctx context.Context) ([]Model, error)
Test(ctx context.Context) *ProviderTestResult
TestModel(ctx context.Context, modelID string) (*ModelTestResult, error)
DoGenerate(ctx context.Context, params GenerateParams) (*GenerateResult, error)
DoStream(ctx context.Context, params GenerateParams) (*StreamResult, error)
}
type ProviderStatus string
const (
ProviderStatusOK ProviderStatus = "ok"
ProviderStatusUnhealthy ProviderStatus = "unhealthy"
ProviderStatusUnreachable ProviderStatus = "unreachable"
)
type ProviderTestResult struct {
Status ProviderStatus
Message string
Error error
}
type ModelTestResult struct {
Supported bool
Message string
}
```
### Models
```go
type ModelType string
const ModelTypeChat ModelType = "chat"
type Model struct {
ID string
DisplayName string
Provider Provider
Type ModelType
MaxTokens int
}
func (m *Model) Test(ctx context.Context) (*ModelTestResult, error)
```
### Messages
```go
type MessageRole string
const (
MessageRoleUser MessageRole = "user"
MessageRoleAssistant MessageRole = "assistant"
MessageRoleSystem MessageRole = "system"
MessageRoleTool MessageRole = "tool"
)
type MessagePartType string
const (
MessagePartTypeText MessagePartType = "text"
MessagePartTypeReasoning MessagePartType = "reasoning"
MessagePartTypeImage MessagePartType = "image"
MessagePartTypeFile MessagePartType = "file"
MessagePartTypeToolCall MessagePartType = "tool-call"
MessagePartTypeToolResult MessagePartType = "tool-result"
)
type MessagePart interface {
PartType() MessagePartType
}
type TextPart struct {
Text string
}
type ReasoningPart struct {
Text string
Signature string
}
type ImagePart struct {
Image string
MediaType string
}
type FilePart struct {
Data string
MediaType string
Filename string
}
type ToolCallPart struct {
ToolCallID string
ToolName string
Input any
}
type ToolResultPart struct {
ToolCallID string
ToolName string
Result any
IsError bool
}
type Message struct {
Role MessageRole
Content []MessagePart
}
func UserMessage(text string, extra ...MessagePart) Message
func SystemMessage(text string) Message
func AssistantMessage(text string) Message
func ToolMessage(results ...ToolResultPart) Message
```
Notes:
- `UserMessage` accepts a text string plus optional extra parts such as `ImagePart`.
- `Message` supports JSON marshal and unmarshal with type discrimination.
### Generation
```go
type FinishReason string
const (
FinishReasonStop FinishReason = "stop"
FinishReasonLength FinishReason = "length"
FinishReasonContentFilter FinishReason = "content-filter"
FinishReasonToolCalls FinishReason = "tool-calls"
FinishReasonError FinishReason = "error"
FinishReasonOther FinishReason = "other"
FinishReasonUnknown FinishReason = "unknown"
)
type ResponseFormatType string
const (
ResponseFormatText ResponseFormatType = "text"
ResponseFormatJSONObject ResponseFormatType = "json_object"
ResponseFormatJSONSchema ResponseFormatType = "json_schema"
)
type ResponseFormat struct {
Type ResponseFormatType
JSONSchema any
}
type GenerateParams struct {
Model *Model
System string
Messages []Message
Tools []Tool
ToolChoice any
ResponseFormat *ResponseFormat
Temperature *float64
TopP *float64
MaxTokens *int
StopSequences []string
FrequencyPenalty *float64
PresencePenalty *float64
Seed *int
ReasoningEffort *string
}
type StepResult struct {
Text string
Reasoning string
FinishReason FinishReason
RawFinishReason string
Usage Usage
ToolCalls []ToolCall
ToolResults []ToolResult
Response ResponseMetadata
Messages []Message
}
type GenerateResult struct {
Text string
Reasoning string
FinishReason FinishReason
RawFinishReason string
Usage Usage
Sources []Source
Files []GeneratedFile
ToolCalls []ToolCall
ToolResults []ToolResult
Response ResponseMetadata
Steps []StepResult
Messages []Message
}
```
### Generate Options
```go
type GenerateOption func(*generateConfig)
func WithModel(model *Model) GenerateOption
func WithMessages(messages []Message) GenerateOption
func WithSystem(text string) GenerateOption
func WithTools(tools []Tool) GenerateOption
func WithToolChoice(choice any) GenerateOption
func WithResponseFormat(rf ResponseFormat) GenerateOption
func WithTemperature(t float64) GenerateOption
func WithTopP(topP float64) GenerateOption
func WithMaxTokens(n int) GenerateOption
func WithStopSequences(s []string) GenerateOption
func WithFrequencyPenalty(penalty float64) GenerateOption
func WithPresencePenalty(penalty float64) GenerateOption
func WithSeed(s int) GenerateOption
func WithReasoningEffort(effort string) GenerateOption
func WithMaxSteps(n int) GenerateOption
func WithOnFinish(fn func(*GenerateResult)) GenerateOption
func WithOnStep(fn func(*StepResult) *GenerateParams) GenerateOption
func WithPrepareStep(fn func(*GenerateParams) *GenerateParams) GenerateOption
func WithApprovalHandler(fn func(ctx context.Context, call ToolCall) (bool, error)) GenerateOption
```
Behavior notes:
- `WithMaxSteps(0)` is the default single-call mode.
- `WithMaxSteps(N)` enables automatic tool execution for up to `N` LLM calls.
- `WithMaxSteps(-1)` means unlimited loop until the model stops requesting tools.
- `WithToolChoice` accepts `"auto"`, `"none"`, or `"required"`.
### Tools
```go
type ToolExecuteFunc func(ctx *ToolExecContext, input any) (any, error)
type ToolExecContext struct {
context.Context
ToolCallID string
ToolName string
SendProgress func(content any)
}
type Tool struct {
Name string
Description string
Parameters any
Execute ToolExecuteFunc
RequireApproval bool
}
func NewTool[T any](
name, description string,
execute func(ctx *ToolExecContext, input T) (any, error),
) Tool
type ToolCall struct {
ToolCallID string
ToolName string
Input any
}
type ToolResult struct {
ToolCallID string
ToolName string
Input any
Output any
IsError bool
}
```
### Streaming
```go
type StreamPartType string
const (
StreamPartTypeTextStart StreamPartType = "text-start"
StreamPartTypeTextDelta StreamPartType = "text-delta"
StreamPartTypeTextEnd StreamPartType = "text-end"
StreamPartTypeReasoningStart StreamPartType = "reasoning-start"
StreamPartTypeReasoningDelta StreamPartType = "reasoning-delta"
StreamPartTypeReasoningEnd StreamPartType = "reasoning-end"
StreamPartTypeToolInputStart StreamPartType = "tool-input-start"
StreamPartTypeToolInputDelta StreamPartType = "tool-input-delta"
StreamPartTypeToolInputEnd StreamPartType = "tool-input-end"
StreamPartTypeToolCall StreamPartType = "tool-call"
StreamPartTypeToolResult StreamPartType = "tool-result"
StreamPartTypeToolError StreamPartType = "tool-error"
StreamPartTypeToolOutputDenied StreamPartType = "tool-output-denied"
StreamPartTypeToolApprovalRequest StreamPartType = "tool-approval-request"
StreamPartTypeToolProgress StreamPartType = "tool-progress"
StreamPartTypeSource StreamPartType = "source"
StreamPartTypeFile StreamPartType = "file"
StreamPartTypeStart StreamPartType = "start"
StreamPartTypeFinish StreamPartType = "finish"
StreamPartTypeStartStep StreamPartType = "start-step"
StreamPartTypeFinishStep StreamPartType = "finish-step"
StreamPartTypeError StreamPartType = "error"
StreamPartTypeAbort StreamPartType = "abort"
StreamPartTypeRaw StreamPartType = "raw"
)
type StreamPart interface {
Type() StreamPartType
}
type TextStartPart struct {
ID string
ProviderMetadata map[string]any
}
type TextDeltaPart struct {
ID string
Text string
ProviderMetadata map[string]any
}
type TextEndPart struct {
ID string
ProviderMetadata map[string]any
}
type ReasoningStartPart struct {
ID string
ProviderMetadata map[string]any
}
type ReasoningDeltaPart struct {
ID string
Text string
ProviderMetadata map[string]any
}
type ReasoningEndPart struct {
ID string
ProviderMetadata map[string]any
}
type ToolInputStartPart struct {
ID string
ToolName string
ProviderMetadata map[string]any
}
type ToolInputDeltaPart struct {
ID string
Delta string
ProviderMetadata map[string]any
}
type ToolInputEndPart struct {
ID string
ProviderMetadata map[string]any
}
type StreamToolCallPart struct {
ToolCallID string
ToolName string
Input any
}
type StreamToolResultPart struct {
ToolCallID string
ToolName string
Input any
Output any
}
type StreamToolErrorPart struct {
ToolCallID string
ToolName string
Error error
}
type ToolOutputDeniedPart struct {
ToolCallID string
ToolName string
}
type ToolApprovalRequestPart struct {
ApprovalID string
ToolCallID string
ToolName string
Input any
}
type ToolProgressPart struct {
ToolCallID string
ToolName string
Content any
}
type StreamSourcePart struct {
Source Source
}
type StreamFilePart struct {
File GeneratedFile
}
type StartPart struct{}
type FinishPart struct {
FinishReason FinishReason
RawFinishReason string
TotalUsage Usage
}
type StartStepPart struct{}
type FinishStepPart struct {
FinishReason FinishReason
RawFinishReason string
Usage Usage
Response ResponseMetadata
ProviderMetadata map[string]any
}
type ErrorPart struct {
Error error
}
type AbortPart struct {
Reason string
}
type RawPart struct {
RawValue any
}
type StreamResult struct {
Stream <-chan StreamPart
Steps []StepResult
Messages []Message
}
func (sr *StreamResult) Text() (string, error)
func (sr *StreamResult) ToResult() (*GenerateResult, error)
```
### Usage, Sources, Files, Response Metadata
```go
type Usage struct {
InputTokens int
OutputTokens int
TotalTokens int
ReasoningTokens int
CachedInputTokens int
InputTokenDetails InputTokenDetail
OutputTokenDetails OutputTokenDetail
}
type InputTokenDetail struct {
CacheReadTokens int
CacheCreationTokens int
}
type OutputTokenDetail struct {
TextTokens int
ReasoningTokens int
AudioTokens int
}
type Source struct {
SourceType string
ID string
URL string
Title string
ProviderMetadata map[string]any
}
type GeneratedFile struct {
Data string
MediaType string
}
type ResponseMetadata struct {
ID string
ModelID string
Timestamp time.Time
Headers map[string]string
}
```
### Embeddings
```go
type EmbeddingProvider interface {
DoEmbed(ctx context.Context, params EmbedParams) (*EmbedResult, error)
}
type EmbeddingModel struct {
ID string
Provider EmbeddingProvider
MaxEmbeddingsPerCall int
}
type EmbedParams struct {
Model *EmbeddingModel
Values []string
Dimensions *int
}
type EmbedResult struct {
Embeddings [][]float64
Usage EmbeddingUsage
}
type EmbeddingUsage struct {
Tokens int
}
type EmbedOption func(*embedConfig)
func WithEmbeddingModel(model *EmbeddingModel) EmbedOption
func WithDimensions(d int) EmbedOption
```
## Package `provider/openai/completions`
Implements the OpenAI Chat Completions API and OpenAI-compatible `/chat/completions` backends.
```go
type Provider struct { /* unexported fields */ }
type Option func(*Provider)
func WithAPIKey(apiKey string) Option
func WithBaseURL(baseURL string) Option
func WithHTTPClient(client *http.Client) Option
func New(options ...Option) *Provider
func (p *Provider) Name() string
func (p *Provider) ListModels(ctx context.Context) ([]sdk.Model, error)
func (p *Provider) Test(ctx context.Context) *sdk.ProviderTestResult
func (p *Provider) TestModel(ctx context.Context, modelID string) (*sdk.ModelTestResult, error)
func (p *Provider) ChatModel(id string) *sdk.Model
func (p *Provider) DoGenerate(ctx context.Context, params sdk.GenerateParams) (*sdk.GenerateResult, error)
func (p *Provider) DoStream(ctx context.Context, params sdk.GenerateParams) (*sdk.StreamResult, error)
```
Default option values:
- `WithBaseURL`: `https://api.openai.com/v1`
- `WithHTTPClient`: `&http.Client{}`
Discovery endpoints:
- `ListModels`: `GET /models`
- `Test`: `GET /models?limit=1`
- `TestModel`: `GET /models/{id}`
## Package `provider/openai/responses`
Implements the OpenAI Responses API with reasoning summaries, annotations, and flat input mapping.
```go
type Provider struct { /* unexported fields */ }
type Option func(*Provider)
func WithAPIKey(apiKey string) Option
func WithBaseURL(baseURL string) Option
func WithHTTPClient(client *http.Client) Option
func New(options ...Option) *Provider
func (p *Provider) Name() string
func (p *Provider) ListModels(ctx context.Context) ([]sdk.Model, error)
func (p *Provider) Test(ctx context.Context) *sdk.ProviderTestResult
func (p *Provider) TestModel(ctx context.Context, modelID string) (*sdk.ModelTestResult, error)
func (p *Provider) ChatModel(id string) *sdk.Model
func (p *Provider) DoGenerate(ctx context.Context, params sdk.GenerateParams) (*sdk.GenerateResult, error)
func (p *Provider) DoStream(ctx context.Context, params sdk.GenerateParams) (*sdk.StreamResult, error)
```
Default option values:
- `WithBaseURL`: `https://api.openai.com/v1`
- `WithHTTPClient`: `&http.Client{}`
Discovery endpoints:
- `ListModels`: `GET /models`
- `Test`: `GET /models?limit=1`
- `TestModel`: `GET /models/{id}`
Responses-specific behavior:
- assistant reasoning maps to `GenerateResult.Reasoning`
- URL citation annotations map to `GenerateResult.Sources`
- function-call outputs map to tool-call and tool-result structures
## Package `provider/anthropic/messages`
Implements the Anthropic Messages API.
```go
type ThinkingConfig struct {
Type string
BudgetTokens int
}
type Provider struct { /* unexported fields */ }
type Option func(*Provider)
func WithAPIKey(apiKey string) Option
func WithAuthToken(token string) Option
func WithBaseURL(baseURL string) Option
func WithHTTPClient(client *http.Client) Option
func WithHeaders(headers map[string]string) Option
func WithThinking(cfg ThinkingConfig) Option
func New(options ...Option) *Provider
func (p *Provider) Name() string
func (p *Provider) ListModels(ctx context.Context) ([]sdk.Model, error)
func (p *Provider) Test(ctx context.Context) *sdk.ProviderTestResult
func (p *Provider) TestModel(ctx context.Context, modelID string) (*sdk.ModelTestResult, error)
func (p *Provider) ChatModel(id string) *sdk.Model
func (p *Provider) DoGenerate(ctx context.Context, params sdk.GenerateParams) (*sdk.GenerateResult, error)
func (p *Provider) DoStream(ctx context.Context, params sdk.GenerateParams) (*sdk.StreamResult, error)
```
Default option values:
- `WithBaseURL`: `https://api.anthropic.com/v1`
- default API version header: `2023-06-01`
- `WithHTTPClient`: `&http.Client{}`
Thinking config notes:
- `Type` supports `"enabled"`, `"adaptive"`, or `"disabled"`
- `BudgetTokens` is required when `Type == "enabled"`
Discovery endpoints:
- `ListModels`: `GET /v1/models`
- `Test`: `GET /v1/models?limit=1`
- `TestModel`: `GET /v1/models/{id}`
## Package `provider/google/generativeai`
Implements the Google Generative AI API for Gemini chat models.
```go
type Provider struct { /* unexported fields */ }
type Option func(*Provider)
func WithAPIKey(apiKey string) Option
func WithBaseURL(baseURL string) Option
func WithHTTPClient(client *http.Client) Option
func New(options ...Option) *Provider
func (p *Provider) Name() string
func (p *Provider) ListModels(ctx context.Context) ([]sdk.Model, error)
func (p *Provider) Test(ctx context.Context) *sdk.ProviderTestResult
func (p *Provider) TestModel(ctx context.Context, modelID string) (*sdk.ModelTestResult, error)
func (p *Provider) ChatModel(id string) *sdk.Model
func (p *Provider) DoGenerate(ctx context.Context, params sdk.GenerateParams) (*sdk.GenerateResult, error)
func (p *Provider) DoStream(ctx context.Context, params sdk.GenerateParams) (*sdk.StreamResult, error)
```
Default option values:
- `WithBaseURL`: `https://generativelanguage.googleapis.com/v1beta`
- `WithHTTPClient`: `&http.Client{}`
Model ID rules:
- plain names like `gemini-2.5-flash` are accepted
- full paths like `publishers/google/models/gemini-2.5-flash` are also accepted
Discovery endpoints:
- `ListModels`: `GET /v1beta/models`
- `Test`: `GET /v1beta/models?pageSize=1`
- `TestModel`: `GET /v1beta/models/{id}`
## Package `provider/openai/embedding`
Implements the OpenAI Embeddings API.
```go
type Provider struct { /* unexported fields */ }
type Option func(*Provider)
func WithAPIKey(apiKey string) Option
func WithBaseURL(baseURL string) Option
func WithHTTPClient(client *http.Client) Option
func New(options ...Option) *Provider
func (p *Provider) EmbeddingModel(id string) *sdk.EmbeddingModel
func (p *Provider) DoEmbed(ctx context.Context, params sdk.EmbedParams) (*sdk.EmbedResult, error)
```
Default option values:
- `WithBaseURL`: `https://api.openai.com/v1`
- `WithHTTPClient`: `&http.Client{}`
Behavior notes:
- `EmbeddingModel(id)` returns a model with `MaxEmbeddingsPerCall: 2048`
- `DoEmbed` calls `POST /embeddings` with `encoding_format: "float"`
## Package `provider/google/embedding`
Implements the Google embedding API.
```go
type Provider struct { /* unexported fields */ }
type Option func(*Provider)
func WithAPIKey(apiKey string) Option
func WithBaseURL(baseURL string) Option
func WithHTTPClient(client *http.Client) Option
func WithTaskType(taskType string) Option
func New(options ...Option) *Provider
func (p *Provider) EmbeddingModel(id string) *sdk.EmbeddingModel
func (p *Provider) DoEmbed(ctx context.Context, params sdk.EmbedParams) (*sdk.EmbedResult, error)
```
Default option values:
- `WithBaseURL`: `https://generativelanguage.googleapis.com/v1beta`
- `WithHTTPClient`: `&http.Client{}`
Task type values:
- `RETRIEVAL_QUERY`
- `RETRIEVAL_DOCUMENT`
- `SEMANTIC_SIMILARITY`
- `CLASSIFICATION`
- `CLUSTERING`
- `QUESTION_ANSWERING`
- `FACT_VERIFICATION`
- `CODE_RETRIEVAL_QUERY`
Behavior notes:
- `EmbeddingModel(id)` returns a model with `MaxEmbeddingsPerCall: 2048`
- single-value embedding uses `embedContent`
- multi-value embedding uses `batchEmbedContents`
## Selection Cheatsheet
- Broad OpenAI-compatible chat API: `provider/openai/completions`
- OpenAI Responses features such as reasoning summaries or citation annotations: `provider/openai/responses`
- Claude and extended thinking: `provider/anthropic/messages`
- Gemini chat and tool calling: `provider/google/generativeai`
- OpenAI-compatible embeddings: `provider/openai/embedding`
- Gemini embeddings with task-type tuning: `provider/google/embedding`