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

model

package
v0.1.0-alpha.4 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnchoredAssistantMessage

func AnchoredAssistantMessage(request Request, response Response) domain.Message

AnchoredAssistantMessage attaches exact usage to the assistant response at the precise merged-message boundary that the next provider request sees.

func RequestContextFingerprint

func RequestContextFingerprint(request Request) string

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) Error

func (e *APIError) Error() string

func (*APIError) Retryable

func (e *APIError) Retryable() bool

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.

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

type Anthropic

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

func AnthropicFromEnv

func AnthropicFromEnv() (*Anthropic, bool, error)

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 (a *Anthropic) CreateMessage(ctx context.Context, req Request) (Response, error)

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

type ContextMeasurement struct {
	Tokens int
	Exact  bool
}

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

type ContextProfile struct {
	ContextWindow int
	Found         bool
}

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 NewFake

func NewFake() *Fake

func (*Fake) CreateMessage

func (f *Fake) CreateMessage(_ context.Context, req Request) (Response, error)

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

func (f *Fake) LastRequest() Request

func (*Fake) SetError

func (f *Fake) SetError(err error)

SetError makes subsequent calls return err after recording their request. It is intended for deterministic model-boundary and orchestration tests.

type Request

type Request struct {
	Model     string
	Effort    string
	Speed     string
	System    string
	Messages  []domain.Message
	MaxTokens int
	Tools     []ToolSchema
}

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

type StreamCallbacks struct {
	OnTextDelta     func(index int, text string)
	OnThinkingStart func()
}

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.

type ToolSchema

type ToolSchema struct {
	// Type is set for provider-native server tools. Ordinary client tools leave
	// it empty and provide Description/InputSchema.
	Type        string
	Name        string
	Description string
	InputSchema map[string]any
}

Jump to

Keyboard shortcuts

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