Documentation
¶
Overview ¶
Package record is the record/replay cassette layer.
Every outbound call — search, fetch, academic, LLM — goes through this package. On first run it records request/response pairs to disk; thereafter it replays them. Three consequences, all of which the project needs before the first actor is written:
- Orchestrator and eval tests are deterministic.
- They run in CI without network access.
- They cost nothing, so the eval harness can run on every commit.
Building this after the actors exist means auditing every call site to thread a transport through, which is why it belongs in M0 rather than M2.
Index ¶
Constants ¶
const ( EnvMode = "MOLE_RECORD" EnvDir = "MOLE_CASSETTE_DIR" )
EnvMode and EnvDir configure recording.
Variables ¶
This section is empty.
Functions ¶
func RequestKey ¶
RequestKey derives the cassette key. It deliberately excludes headers: matching on them would make every recording depend on the exact SDK version, user-agent, and auth scheme in use when it was made.
func Slug ¶
Slug turns a run name into a stable, readable filename.
Readability is the point: a cassette is reviewed in a pull request, and "what-is-the-consensus-on-byte-level-llms.json" is reviewable in a way that a hash is not. Same question in, same file out, so a re-record replaces the recording it supersedes rather than accumulating beside it.
Types ¶
type Cassette ¶
type Cassette struct {
// contains filtered or unexported fields
}
Cassette is a set of interactions backed by one JSON file.
func LoadCassette ¶
LoadCassette reads a cassette, returning an empty one if the file is absent.
type ErrCassetteMiss ¶
ErrCassetteMiss is returned in ModeReplay when no interaction matches.
func (*ErrCassetteMiss) Error ¶
func (e *ErrCassetteMiss) Error() string
type Interaction ¶
type Interaction struct {
Key string `json:"key"`
Request ReqSnapshot `json:"request"`
Response RespSnapshot `json:"response"`
}
Interaction is one recorded request/response pair.
type Mode ¶
type Mode string
const ( // ModeOff passes everything through untouched. ModeOff Mode = "off" // ModeRecord always hits the network and overwrites stored interactions. ModeRecord Mode = "record" // ModeReplay never hits the network; a miss is an error. ModeReplay Mode = "replay" // ModeAuto replays what exists and records what does not. Convenient // locally, but do not use it in CI: a cassette miss would silently make a // real network call and a real charge. ModeAuto Mode = "auto" )
func ModeFromEnv ¶
ModeFromEnv reports the configured mode without opening anything.
Separate from FromEnv because some checks have to happen BEFORE a cassette is touched. Refusing a worker pool is one: in replay, FromEnv fails on a missing cassette first, so a guard placed after it never runs and the caller is told the recording is absent rather than that the request was never allowed.
type Recorder ¶
type Recorder struct {
Mode Mode
Cassette *Cassette
Path string
// contains filtered or unexported fields
}
Recorder is a cassette plus the client that reads and writes it.
func FromEnv ¶
FromEnv builds a Recorder for a named run from MOLE_RECORD and MOLE_CASSETTE_DIR. With recording off it returns a Recorder that passes everything through, so callers need no conditional.
func (*Recorder) Wrap ¶
func (r *Recorder) Wrap(base http.RoundTripper) http.RoundTripper
Wrap adapts a transport that a caller has already built.
The fetcher is the one provider that cannot simply be handed a client: its transport carries the egress guard's DialContext, and replacing it would bypass SSRF protection. Wrapping instead keeps the guard underneath, so a recording still goes through it and a replay never reaches a socket at all.
type ReqSnapshot ¶
type RespSnapshot ¶
type Transport ¶
type Transport struct {
Mode Mode
Cassette *Cassette
Base http.RoundTripper
}
Transport is an http.RoundTripper that records or replays. One transport covers search, fetch, academic providers, and any LLM SDK that accepts a custom *http.Client — which is most of the outbound surface.
func NewTransport ¶
func NewTransport(mode Mode, cassette *Cassette, base http.RoundTripper) *Transport
NewTransport wraps base. A nil base uses http.DefaultTransport.