Documentation
¶
Overview ¶
Package provider turns a context of state file records into one LLM request and the streamed response back into records. Six envelopes exist. Same context, same envelope, same bytes: the step record's request hash proves it. For claude-code the bytes are what the harness hands the claude binary.
Index ¶
- Variables
- func Events(r io.Reader, fn func(event, data string) error) error
- func Normal(step statefile.Header) bool
- func Split(ctx []statefile.Record) (system, rest []statefile.Record)
- type Cache
- type Call
- type Config
- type Envelope
- type LoginState
- type Prompt
- type Provider
- type Request
- type Tool
- type Turn
Constants ¶
This section is empty.
Variables ¶
var Logins = map[string]func(ctx context.Context, dir string, show func(Prompt), paste <-chan string) error{
"chatgpt": chatgptLogin,
"claude-code": claudeLogin,
}
Logins are the shapes whose user signs in instead of pasting a key. A login shows the user prompts, reads what the user pastes, and returns nil once what the provider needs is in dir.
var Shapes = map[string]func(c Config) Provider{ "anthropic": func(c Config) Provider { return Anthropic(c.URL, c.Key) }, "openai": func(c Config) Provider { return OpenAI(c.URL, c.Key) }, "openai-chat": func(c Config) Provider { return OpenAIChat(c.URL, c.Key) }, "google": func(c Config) Provider { return Gemini(c.URL, c.Key) }, "bedrock": func(c Config) Provider { return Bedrock(c.URL, c.Region, c.Key) }, "chatgpt": func(c Config) Provider { return ChatGPT(c.URL, c.Dir) }, "claude-code": func(c Config) Provider { return ClaudeCode(c.Dir) }, }
Shapes is every wire format a provider in the config may have, each built from the provider's config. The url is the base url the vendor's official SDK takes; the shape appends the API path. An empty url is the vendor's own.
Functions ¶
func Events ¶
Events reads a server-sent event stream and calls fn once per event with its name (may be empty) and joined data. Returns when the stream ends or fn returns an error.
Types ¶
type Cache ¶
Cache is the step record's cache header, facts only. Marks are the ids of the records that end a cache breakpoint. Anthropic and bedrock put one after the system prompt and one after the last user block; openai and gemini place their own, so the mark is the last record sent. TTL is seconds from the step's sent time, set only where the request the harness sends fixes it: anthropic and bedrock. The step's usage says what was read and written.
type Call ¶
type Call struct {
Name string `json:"name"`
Arguments json.RawMessage `json:"arguments"`
}
Call is the body of a call record.
type Config ¶ added in v0.5.5
type Config struct {
Key, URL, Region, Dir string
}
Config is a provider as the harness config has it. Dir is the harness's own directory for this provider, where a login keeps what it needs.
type Envelope ¶
type Envelope interface {
Name() string
Accepts(typ string) bool
Owns(field string) bool
Compile(req Request) (body []byte, cache json.RawMessage, err error)
Stream(resp io.Reader, emit func(statefile.Record)) (statefile.Header, error)
}
Envelope is one wire shape. Name tags the thinking and step records it produces; only thinking with its own name is replayed. Compile is deterministic and returns the cache markers it placed, which go on the step record. Stream calls emit once per block as the stream completes it and returns the step header with usage. Accepts is the media types the envelope encodes as media; a record of any other type goes as text. Owns is the body fields Compile builds from the session, which params may not set.
type LoginState ¶ added in v0.5.5
type LoginState struct {
State string `json:"state"` // pending, done or failed
Error string `json:"error,omitempty"`
Prompt
}
LoginState is a login as the harness's routes show it.
type Prompt ¶ added in v0.5.5
type Prompt struct {
Text string `json:"text"`
URL string `json:"url"`
Code string `json:"code,omitempty"`
Paste bool `json:"paste,omitempty"`
}
Prompt is what a login asks of the user: open URL, enter Code there if one is given, and paste back what Text says if Paste.
type Provider ¶
type Provider struct {
URL string // full endpoint. gemini and bedrock take the model in the path, see Endpoint
Key string
Envelope Envelope
Headers func(req *http.Request, key string) // auth and version headers
Endpoint func(url, model string) string // nil means URL as is
Token func(ctx context.Context) (string, error) // the key of each request, for a login's key that expires; nil means Key
Session string // the header that carries Request.Key, where the vendor routes its cache on a header
// Run, if set, makes the step instead of an HTTP request: claude-code's
// process. It retries what it can itself.
Run func(ctx context.Context, body []byte, emit func(statefile.Record)) (statefile.Header, error)
}
func Bedrock ¶
Bedrock authenticates with a Bedrock API key (AWS_BEARER_TOKEN_BEDROCK), not SigV4. Model is an inference profile id such as us.anthropic.claude-haiku-4-5-20251001-v1:0.
func ClaudeCode ¶ added in v0.5.5
func OpenAIChat ¶
OpenAIChat is the Chat Completions envelope for OpenAI-compatible endpoints. Thinking is reasoning_content, the field DeepSeek, Kimi, GLM and MiMo stream and want back in a tool loop. OpenRouter and OpenCode Go stream it as reasoning instead and read either field back, so it replays as reasoning_content everywhere; a server without it sends none. OpenRouter also streams reasoning_details, which hold the upstream's signed or encrypted reasoning (Claude, GPT, Gemini). Where a step has them they are its thinking record, a JSON array, replayed as reasoning_details.
type Request ¶
type Request struct {
Model string
Key string // record 1's id, the routing key for prefix caches: a copy shares it with the session it copies, as it shares the prefix
Tools []Tool
Context []statefile.Record // statefile.Build output
Params map[string]json.RawMessage
}
Params are the session's vendor fields, see encode.
type Tool ¶
type Tool struct {
Name string
Description string
Schema json.RawMessage // JSON Schema for the arguments object
}
type Turn ¶
type Turn struct {
Assistant bool
Records []statefile.Record
// contains filtered or unexported fields
}
Turns groups the non-system context into alternating turns in API order: user turns hold results, messages, later system records, summaries, and errors; assistant turns hold the blocks one step closed. A message begins with a line naming its via, so the model knows who sent it; media (image, pdf, audio, video) gets that line as a text record before it. The step record ends its assistant turn. A step that closed no blocks, a model that said nothing, is no turn at all: every provider rejects an empty assistant turn, and every provider merges the user turns around it.