Documentation
¶
Overview ¶
Package provider defines the Completer contract a caller uses to complete a chat turn against a language model, plus the request and response shapes the contract carries. The package defines the contract only; see provider/anthropic for the Messages API adapter. See ../docs/plans/provider.md for the locked surface and ../docs/plans/agents/phase29_provider.md for the design rationale.
Map: types.go = Role and its constants, Message, Message.Validate, ToolDefinition, ToolCall, Usage, Request, Response, Chunk, Chunk.Validate, and the sentinel errors ErrToolCallIDUnexpected, ErrToolCallIDRequired, ErrUnknownRole, ErrChunkErrDoneConflict, ErrReasoningContentUnexpected; request.go = ToolChoice and its constants, Request.Validate, ErrToolChoiceInvalid, ReasoningDialect, CacheStyle and its constants, CacheUsage, WebSearchResult; completer.go = Completer, ContextAccountant, ReasoningPolicy; reasoning.go = ReasoningEffort and its constants, ReasoningBlock, RedactBlock; runturn.go = RunTurn. Contribution rules: ../AGENTS.md.
Index ¶
- Constants
- Variables
- type CacheStyle
- type CacheUsage
- type Chunk
- type Completer
- type ContextAccountant
- type Message
- type ReasoningBlock
- type ReasoningDialect
- type ReasoningEffort
- type ReasoningPolicy
- type Request
- type Response
- type Role
- type TokenEstimator
- type ToolCall
- type ToolChoice
- type ToolDefinition
- type Usage
- type WebSearchResult
Constants ¶
const MaxNameBytes = 128
MaxNameBytes bounds Message.Name when set.
const ReasoningEventKind = "reasoning"
ReasoningEventKind is the contextstate.SourceEvent.Kind value that marks a reasoning trace. The one place the literal appears; contextsession.IsReasoningEvent compares against this constant, never the literal.
Variables ¶
var ( // ErrToolCallIDUnexpected is Validate's error when ToolCallID is // non-empty on a Message whose Role is not RoleTool. ErrToolCallIDUnexpected = errors.New("provider: tool call id unexpected outside RoleTool") // ErrToolCallIDRequired is Validate's error when ToolCallID is // empty on a RoleTool Message. ErrToolCallIDRequired = errors.New("provider: tool call id required for RoleTool") // ErrUnknownRole is Validate's error when Role is outside the four // declared constants. ErrUnknownRole = errors.New("provider: unknown role") // ErrToolCallsUnexpected is Validate's error when ToolCalls is // non-empty on a Message whose Role is not RoleAssistant. ErrToolCallsUnexpected = errors.New("provider: tool calls unexpected outside RoleAssistant") // ErrChunkErrDoneConflict is Chunk.Validate's error when a Chunk // carries both a non-nil Err and Done == true. ErrChunkErrDoneConflict = errors.New("provider: chunk carries both Err and Done") // ErrStreamClosedEarly is drainStream's error when a Completer's // ChatStream channel closes before any chunk carries Done == true // or a non-nil Err. RunTurn returns the zero Response alongside // this error; it never returns a partial aggregation. ErrStreamClosedEarly = errors.New("provider: stream closed before a terminal chunk") // ErrNameUnexpected is Validate's error when Name is non-empty on a // Role other than RoleUser or RoleTool. ErrNameUnexpected = errors.New("provider: name unexpected outside RoleUser and RoleTool") // ErrNameInvalid is Validate's error when a non-empty Name exceeds // MaxNameBytes, is not valid UTF-8, or carries a control character. ErrNameInvalid = errors.New("provider: name is invalid or too long") // ErrPromptTooLong marks a provider's rejection of a prompt that // exceeds the model's context window. A Completer returns or wraps // it; provider ships no implementation itself. ErrPromptTooLong = errors.New("provider: prompt exceeds the model context window") // ErrReasoningContentUnexpected is Validate's error when // ReasoningContent is non-empty on a Message whose Role is not // RoleAssistant. ErrReasoningContentUnexpected = errors.New("provider: reasoning content unexpected outside RoleAssistant") )
Sentinel errors for Message.Validate and Chunk.Validate; test with errors.Is.
var ErrToolChoiceInvalid = errors.New("provider: tool choice is not auto, none, or empty")
ErrToolChoiceInvalid is Request.Validate's error when ToolChoice holds any value other than "", ToolChoiceAuto, or ToolChoiceNone.
Functions ¶
This section is empty.
Types ¶
type CacheStyle ¶
type CacheStyle string
CacheStyle names how a provider's wire format expresses prompt-cache reuse for one turn.
const ( CacheStyleNone CacheStyle = "none" CacheStyleImplicit CacheStyle = "implicit" CacheStyleExplicit CacheStyle = "explicit" )
The three cache styles a provider's response may report.
type CacheUsage ¶
type CacheUsage struct {
Reported bool
Style CacheStyle
InputTokens int
CachedInputTokens int
CacheWriteTokens int
}
CacheUsage reports provider-side prompt-cache accounting for one turn. Reported false means the provider's response carried none of the recognized cache-usage fields; every other field is meaningless when Reported is false, the same "reported flag gates the rest" shape TokenEstimator's callers already expect from Usage-adjacent types.
type Chunk ¶
type Chunk struct {
Delta string
ToolCallDelta *ToolCall
Done bool
Usage Usage
FinishReason string
Err error
ReasoningDelta string
CacheUsage CacheUsage
WebSearch []WebSearchResult
}
Chunk is one increment of a streamed response. Done is true only on the final chunk that completes without error; Usage, FinishReason, CacheUsage, and WebSearch are the zero value until then. ToolCallDelta is non-nil only on a chunk that carries a tool-call fragment. ReasoningDelta concatenates, in arrival order, into Response.Message.ReasoningContent, the same way Delta concatenates into Response.Message.Content. Err is nil on every chunk except a terminal chunk that reports a mid-stream failure; when a chunk carries a non-nil Err, the channel closes after it and no further chunk follows. A chunk never carries both a non-nil Err and Done == true.
type Completer ¶
type Completer interface {
Name() string
Chat(ctx context.Context, req Request) (Response, error)
ChatStream(ctx context.Context, req Request) (<-chan Chunk, error)
}
Completer is the required contract a caller uses to complete a chat turn against a language model. Name returns the provider's own label, for logs and error messages. Chat always waits for the complete response before it returns; a caller ignores Request.Stream when it calls Chat. ChatStream always returns a channel of Chunk values immediately; the channel closes after the final chunk.
type ContextAccountant ¶
type ContextAccountant interface {
ContextWindow() int
}
ContextAccountant is an optional Completer capability exposing the bound model's maximum token count across one request. A caller type-asserts: if ca, ok := c.(provider.ContextAccountant); ok.
type Message ¶
type Message struct {
Role Role
Content string
Name string
ToolCallID string
ToolCalls []ToolCall
ReasoningContent string
CreatedAt time.Time
}
Message is one turn in the conversation Request.Messages carries. ToolCallID is set only, and always, on a RoleTool message; it names the ToolCall.ID the message answers. ToolCalls is non-empty only on a RoleAssistant message; it holds the calls that assistant turn made. Name is legal only on RoleUser and RoleTool messages; an empty Name is legal on every role. See MaxNameBytes for the bound. ReasoningContent carries a model's chain-of-thought for one assistant turn, verbatim, for a completer whose provider requires the caller to echo it back on a later tool-call turn; it is legal only on RoleAssistant. CreatedAt is wall-clock time for when the message entered the caller's own history; its zero value means unknown, and every role may carry it or omit it.
func (Message) Validate ¶
Validate enforces the ToolCallID/Role pairing rule, the closed set of Role constants, the Name rule, the ToolCalls rule, and the ReasoningContent rule. It checks Role legality first: a Role outside the four constants always returns ErrUnknownRole, regardless of Name, ToolCallID, ToolCalls, or ReasoningContent. For one of the four known roles, Validate next checks the Name rule: ErrNameUnexpected when Name is non-empty on a Role other than RoleUser or RoleTool; ErrNameInvalid when a non-empty Name exceeds MaxNameBytes, is not valid UTF-8, or carries a control character. Then Validate checks the ToolCallID pairing rule: ErrToolCallIDUnexpected when ToolCallID is non-empty on a non-RoleTool message; ErrToolCallIDRequired when ToolCallID is empty on a RoleTool message. Next, Validate rejects a non-empty ToolCalls on any known Role other than RoleAssistant with ErrToolCallsUnexpected. Finally, Validate rejects a non-empty ReasoningContent on any known Role other than RoleAssistant with ErrReasoningContentUnexpected. RunTurn calls Validate on every entry of Request.Messages before it dispatches.
type ReasoningBlock ¶
ReasoningBlock is one reasoning segment a model produced. Content is empty whenever Redacted is true. ReasoningBlock never appears on Message or Response; it is a value a caller carries alongside its own session state.
func RedactBlock ¶
func RedactBlock(b ReasoningBlock) ReasoningBlock
RedactBlock returns b with Content cleared and Redacted set true. Idempotent: a second call on an already-redacted block returns it unchanged.
type ReasoningDialect ¶
type ReasoningDialect string
ReasoningDialect names the wire dialect a Completer should use to carry ReasoningEffort to its provider. The empty value means "use the completer's own default dialect". provider defines no closed set of dialect names; a concrete client package owns its own vocabulary and compares against its own constants, never a provider literal.
type ReasoningEffort ¶
type ReasoningEffort string
ReasoningEffort is the provider-neutral reasoning effort vocabulary, closed by four constants below. A ReasoningPolicy implementation may report any of these from ReasoningEffort() string; the interface's return type stays string to keep the existing lock, but a caller compares against these constants instead of a literal.
const ( ReasoningEffortNone ReasoningEffort = "none" ReasoningEffortLow ReasoningEffort = "low" ReasoningEffortMedium ReasoningEffort = "medium" ReasoningEffortHigh ReasoningEffort = "high" )
The four reasoning effort levels.
type ReasoningPolicy ¶
type ReasoningPolicy interface {
ReasoningEffort() string
}
ReasoningPolicy is an optional Completer capability exposing the configured reasoning-effort level for a model that supports extended reasoning. A caller type-asserts: if rp, ok := c.(provider.ReasoningPolicy); ok.
type Request ¶
type Request struct {
Model string
Messages []Message
Tools []ToolDefinition
Stream bool
// StreamingWriter, when non-nil, receives bytes a Completer
// chooses to emit during the call. This SDK writes nothing to
// it yet; it is an opt-in pass-through for a completer that
// mirrors its stream. The zero value is nil and changes no
// behavior.
StreamingWriter io.Writer
Temperature *float64
MaxTokens *int
ToolChoice ToolChoice
Timeout time.Duration
SessionID string
DisableProviderReplay bool
ReasoningEffort ReasoningEffort
ReasoningDialect ReasoningDialect
}
Request is the input to every Completer method. An empty Model means the implementation's own default. Tools may be empty when the caller offers none. Temperature and MaxTokens are pointers: nil means "use the completer's own default", a non-nil pointer to zero is a caller instruction. ToolChoice's zero value means unspecified. Timeout's zero value means no caller-side timeout override. SessionID and DisableProviderReplay use their natural zero-value "not set" reading. ReasoningEffort's zero value means send no reasoning field at all. ReasoningDialect's zero value means use the completer's own default dialect. See Request.Validate for the ToolChoice rule.
type Response ¶
type Response struct {
Model string
Message Message
ToolCalls []ToolCall
Usage Usage
FinishReason string
CacheUsage CacheUsage
WebSearch []WebSearchResult
}
Response is the aggregated result of one turn. Model echoes the model that actually served the request, which may differ from Request.Model on a provider that redirects to a fallback. ToolCalls is empty when the model returned plain text. Response carries no separate reasoning-content field: Message.ReasoningContent already holds it, since Response embeds Message. CacheUsage and WebSearch hold the terminal Chunk's values on the streamed path, or the Completer's own values on the non-streamed path.
func RunTurn ¶
RunTurn dispatches on req.Stream: it calls c.Chat when false, and calls c.ChatStream, drains, and aggregates when true. It calls req.Validate() once, before it validates any Messages entry and before it dispatches to either Completer method; a Validate failure returns the zero Response and that error, unwrapped. It then calls Message.Validate on every entry of req.Messages, in order; the first invalid entry stops validation and RunTurn returns the zero Response and that error, unwrapped, without calling either Completer method. On the streamed path RunTurn selects on ctx.Done() during drain; when ctx finishes first, RunTurn discards any partial aggregation and returns the zero Response alongside ctx.Err(). RunTurn returns the first error either Completer method returns, unwrapped, alongside the zero Response. When the ChatStream channel closes before any chunk carries Done == true or a non-nil Err, RunTurn discards any partial aggregation and returns the zero Response alongside ErrStreamClosedEarly; a mid-stream failure never returns a partial Response. On the streamed path Response.Message.ToolCalls carries the same merged calls as Response.ToolCalls after every call, and Response.Message .ReasoningContent carries the concatenated ReasoningDelta text. buildResponse assigns both ToolCalls fields the same slice and copies the terminal Chunk's CacheUsage and WebSearch onto Response.
type TokenEstimator ¶
TokenEstimator is an optional Completer capability exposing a best-effort token count for a given Request, ahead of a Chat or ChatStream call. A caller type-asserts: if te, ok := c.(provider.TokenEstimator); ok. EstimateTokens takes the same Request the caller intends to pass to Chat, so an implementation can account for every field, including Messages and Tools. The estimate is best-effort and provider-defined; provider states no accuracy guarantee and computes no estimate itself. EstimateTokens returns a non-nil error when it cannot produce an estimate for the given Request; it returns (0, nil) only for a Request the implementation judges to cost zero tokens, never as a failure signal.
type ToolCall ¶
ToolCall is one call the model requests, or one fragment of a call while it streams. Index is the vendor-assigned position of this tool call within the turn. Arguments holds the raw argument bytes; the caller decodes them against the matching ToolDefinition.Schema.
type ToolChoice ¶
type ToolChoice string
ToolChoice controls whether and how a completion may call a tool. The empty value means unspecified: the completer's own default applies. ToolChoiceAuto and ToolChoiceNone are the two closed, provider-neutral overrides Request.Validate accepts.
const ( ToolChoiceAuto ToolChoice = "auto" ToolChoiceNone ToolChoice = "none" )
The two closed ToolChoice overrides Request.Validate accepts, alongside the empty "unspecified" value.
type ToolDefinition ¶
ToolDefinition names one tool a model may call. Schema holds the tool's parameter schema as raw bytes; provider does not parse it.
type Usage ¶
Usage reports token accounting for one completed turn. CachedTokens counts prompt tokens served from a provider-side cache, when the provider reports one; it is zero otherwise.
type WebSearchResult ¶
type WebSearchResult struct {
Title string
Content string
Link string
Media string
Icon string
Refer string
PublishDate string
}
WebSearchResult is one provider-supplied search result attached to a completion. Every field is a raw transport-level string; provider does not interpret or render it. No JSON tag: provider carries in-process values only and defines no wire format of its own.