Documentation
¶
Overview ¶
Package model defines the inference client the agent core calls. The interface is deliberately small and vendor-neutral so the transport (real Messages API, offline fake, or another provider) is swappable without touching the agent core or the domain.
Index ¶
- func AnchoredAssistantMessage(request Request, response Response) domain.Message
- func RequestContextFingerprint(request Request) string
- type APIError
- type Anthropic
- func (a *Anthropic) CreateMessage(ctx context.Context, req Request) (Response, error)
- func (a *Anthropic) CreateMessageStream(ctx context.Context, req Request, onDelta func(index int, text string)) (Response, error)
- func (a *Anthropic) CreateMessageStreamWithCallbacks(ctx context.Context, req Request, callbacks StreamCallbacks) (Response, error)
- type AnthropicConfig
- type Client
- type ContextLimits
- type ContextMeasurement
- type ContextProfile
- type ErrorKind
- type Fake
- type Request
- type Response
- type RichStreamingClient
- type StreamCallbacks
- type ToolSchema
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AnchoredAssistantMessage ¶
AnchoredAssistantMessage attaches exact usage to the assistant response at the precise merged-message boundary that the next provider request sees.
func RequestContextFingerprint ¶
RequestContextFingerprint intentionally excludes Messages. Message-prefix integrity is checked independently so messages added after an exact anchor can be estimated as a delta.
Types ¶
type APIError ¶
type APIError struct {
Kind ErrorKind
StatusCode int
Type string
Message string
RequestID string
RetryAfter time.Duration
Cause error
}
APIError is a typed, sanitized failure returned by a model provider. Message is bounded and contains response-body text only; RequestID is safe provider correlation metadata. Cause is set for transport failures so errors.Is/As continue to work without exposing request headers or credentials.
func (*APIError) Retryable ¶
Retryable reports whether repeating the same logical model request can reasonably succeed without changing caller input or operator configuration. Unknown transport/server failures retain the previous retry-by-default behavior; known permanent 4xx failures terminate honestly instead of leaving a Temporal Activity retrying forever.
type Anthropic ¶
type Anthropic struct {
// contains filtered or unexported fields
}
func AnthropicFromEnv ¶
AnthropicFromEnv builds a client from environment variables. It returns (nil, false, nil) when the base URL or key is unset, so the caller falls back to the offline fake without error.
func NewAnthropic ¶
func NewAnthropic(cfg AnthropicConfig) (*Anthropic, error)
func (*Anthropic) CreateMessage ¶
func (*Anthropic) CreateMessageStream ¶
func (a *Anthropic) CreateMessageStream( ctx context.Context, req Request, onDelta func(index int, text string), ) (Response, error)
CreateMessageStream opens the Messages-API server-sent-events stream ("stream": true) and decodes it incrementally. It scans the SSE body line by line, parses each `data:` payload as JSON, and dispatches on the top-level `type`:
- content_block_start — opens a block at `index`; for tool_use it captures id/name so the block can be assembled from later deltas.
- content_block_delta — for a text_delta it accumulates text and calls onDelta(index, text) per chunk; for an input_json_delta it accumulates the tool_use partial_json (no onDelta — tool input is not previewed).
- content_block_stop — finalizes a block; a tool_use block's accumulated partial_json is parsed into its input map here.
- message_delta — captures stop_reason.
- message_stop — end of stream.
It assembles and returns the final Response (content blocks in index order + stop_reason). A non-2xx status is handled exactly as the non-streaming path: the sanitized, length-bounded upstream body is folded into the returned error. The request context threads through the HTTP read, so a cancelled context aborts the stream.
tool_use streaming coverage: text is fully incremental; tool_use blocks are assembled from content_block_start + accumulated input_json_delta and parsed at content_block_stop. This is enough for the tool loop (which needs the complete tool call), but partial_json is not surfaced incrementally.
func (*Anthropic) CreateMessageStreamWithCallbacks ¶
func (a *Anthropic) CreateMessageStreamWithCallbacks( ctx context.Context, req Request, callbacks StreamCallbacks, ) (Response, error)
CreateMessageStreamWithCallbacks adds privacy-safe lifecycle signals to the basic streaming client. In particular, thinking is start-only: no reasoning bytes cross this callback boundary.
type AnthropicConfig ¶
type AnthropicConfig struct {
BaseURL string // e.g. https://api.anthropic.com
APIKey string
Model string
AuthHeader string // "x-api-key" (default) or "authorization-bearer"
HTTPClient *http.Client
}
AnthropicConfig configures the real Messages-API client. Everything comes from the caller (env in production); no value is hardcoded and no credential is ever compiled in or logged.
type Client ¶
type Client interface {
CreateMessage(ctx context.Context, req Request) (Response, error)
// CreateMessageStream is the streaming variant of CreateMessage. It invokes
// onDelta once per text delta (index is the content-block index; currently
// always 0), in order, as the reply is produced, then returns the same
// Response CreateMessage would return for the same request. Callers that do
// not care about incremental deltas can call CreateMessage instead.
//
// When the response is not streamable text (e.g. a tool_use turn), onDelta
// is not called and the full Response is returned directly.
CreateMessageStream(ctx context.Context, req Request, onDelta func(index int, text string)) (Response, error)
}
type ContextLimits ¶
type ContextLimits struct {
ContextWindow int
MaxOutputTokens int
InputLimit int
CompactThreshold int
GrowthReserve int
}
ContextLimits are the model-specific thresholds for one request. InputLimit reserves the actual request max output. CompactThreshold leaves additional headroom for one unusually large model/tool round.
func RequestContextLimits ¶
func RequestContextLimits(request Request) ContextLimits
type ContextMeasurement ¶
func MeasureRequestContext ¶
func MeasureRequestContext(request Request) ContextMeasurement
MeasureRequestContext follows CCB's canonical rule: use the most recent provider-reported usage whose request and measured message prefix still match, then estimate only content appended after it. If no anchor is safe, estimate the complete request including system and tools.
type ContextProfile ¶
ContextProfile is the small portion of Catwalk model metadata needed for request admission. Found is false for custom Claude-compatible model ids, which use the conservative fallback window.
func ResolveContextProfile ¶
func ResolveContextProfile(modelID string) ContextProfile
ResolveContextProfile uses Catwalk's embedded Anthropic catalog. A dated provider id may extend a known catalog id, but a shorter ambiguous id must never inherit a larger model's window. Arbitrary router and test ids retain the conservative Claude-compatible fallback.
type ErrorKind ¶
type ErrorKind string
ErrorKind classifies failures at the model-provider boundary. The values are provider-neutral control-plane categories: provider-specific wire error types remain available on APIError.Type for diagnostics.
const ( ErrorUnknown ErrorKind = "unknown" ErrorInvalidRequest ErrorKind = "invalid_request" ErrorAuthentication ErrorKind = "authentication" ErrorBilling ErrorKind = "billing" ErrorPermission ErrorKind = "permission" ErrorNotFound ErrorKind = "not_found" ErrorConflict ErrorKind = "conflict" ErrorRequestTooLarge ErrorKind = "request_too_large" ErrorRateLimit ErrorKind = "rate_limit" ErrorServer ErrorKind = "server" ErrorTimeout ErrorKind = "timeout" ErrorOverloaded ErrorKind = "overloaded" ErrorTransport ErrorKind = "transport" )
type Fake ¶
type Fake struct {
// contains filtered or unexported fields
}
Fake is a deterministic offline Client. It echoes the last user text block as an assistant reply and reports end_turn, so the agent core and app layer can be tested with no network. It records the last request for assertions.
func (*Fake) CreateMessage ¶
func (*Fake) CreateMessageStream ¶
func (f *Fake) CreateMessageStream(ctx context.Context, req Request, onDelta func(index int, text string)) (Response, error)
CreateMessageStream mirrors CreateMessage but streams the reply text in deterministic chunks before returning. It computes the same Response CreateMessage would, then, for a text reply, splits the text into >=2 ordered chunks and calls onDelta(0, chunk) for each. The concatenation of the chunks equals the final text, so streamed and non-streamed callers observe identical content. When the turn is a tool_use (the tool branch), no text is streamed: onDelta is not called and the tool_use Response is returned directly.
func (*Fake) LastRequest ¶
type Response ¶
type Response struct {
Content []domain.ContentBlock
StopReason string
Usage domain.TokenUsage
}
type RichStreamingClient ¶
type RichStreamingClient interface {
CreateMessageStreamWithCallbacks(
ctx context.Context,
req Request,
callbacks StreamCallbacks,
) (Response, error)
}
RichStreamingClient is an optional extension implemented by transports that can distinguish privacy-safe stream lifecycle signals. Client remains the compatibility floor for simple providers and existing test doubles.
type StreamCallbacks ¶
StreamCallbacks exposes only public, privacy-safe progress signals. Thinking content is intentionally absent: callers may announce that thinking began, but must never receive provider reasoning through this channel.