Documentation
¶
Overview ¶
Package api provides an HTTP API server over the derived sessions/traces/spans read model.
Index ¶
- Constants
- func CompileOpenAPI(ctx context.Context, docs tapesoapi.TypeDocs) (*tapesoapi.CompiledDoc, error)
- func DefaultContractVersions() []cassette.ContractVersion
- func NewOpenAPIParser(docs tapesoapi.TypeDocs) *tapesoapi.Parser
- type Config
- type Discovery
- type DiscoveryDepends
- type DiscoveryEntry
- type DiscoverySetting
- type MCPError
- type MCPRequest
- type MCPResponse
- type MainUsage
- type Metrics
- type ModelUsage
- type PayloadMode
- type RawTurnHeaderItem
- type RawTurnListResponse
- type Server
- func (s *Server) OpenAPIParser() *tapesoapi.Parser
- func (s *Server) RefreshCassetteSpecs(ctx context.Context) []error
- func (s *Server) Run() error
- func (s *Server) RunWithListener(listener net.Listener) error
- func (s *Server) SetCassetteSources(sources []string)
- func (s *Server) Shutdown() error
- func (s *Server) StartCassetteSpecRefresh(ctx context.Context, interval time.Duration)
- type SessionDetailResponse
- type SessionItem
- type SessionListResponse
- type SessionRollup
- type SessionTracesResponse
- type SessionUsage
- type SpanItem
- type SpanLinkItem
- type StatsResponse
- type TraceDetail
- type TraceItem
- type TraceListResponse
- type TraceUsage
- type TreeTask
Constants ¶
const ProjectionSchema = "2026-06-15"
ProjectionSchema is the compatibility date of the derived projection generation currently served (the dated *_20260615 table family). It is stamped onto the wire `schema` field; a future generation bumps this in lockstep with a new dated table family (derived_projection_schemas).
Variables ¶
This section is empty.
Functions ¶
func CompileOpenAPI ¶ added in v0.30.0
CompileOpenAPI builds the read API's published contract.
It constructs a server purely to make it register its routes, then compiles what that registration produced. Generating from the real construction path rather than from a description of it is the point: there is no second list of routes to fall out of step with the first.
The server is never started and never serves a request, so it is given no driver — the handlers it registers are function values, and nothing calls them.
func DefaultContractVersions ¶ added in v0.30.0
func DefaultContractVersions() []cassette.ContractVersion
DefaultContractVersions returns the tapes contracts this build of core serves.
This is the API server's fact to hold, and it lives next to the handlers that serve the surface it names. It is deliberately not a constant in pkg/cassette: that package is the vocabulary a cassette uses to describe itself, and a cassette declaring "I read tapes v1" must not depend on a package that also asserts which core is running. The dependency goes one way — core reads a cassette's declaration and decides.
It is a set rather than a single value so a deployment can serve a new contract while still admitting cassettes built against the previous one. That is the only way to roll a fleet of cassettes forward without a flag day, and it costs nothing to allow for now.
func NewOpenAPIParser ¶ added in v0.30.0
NewOpenAPIParser returns a parser configured the way both this server and the contract generator need it.
docs may be nil, and is nil in the running server: a deployed binary has no source tree to read prose out of. It is non-nil under `tapes dev openapi`, which points the doc reader at a checkout so the compiled document carries the prose sitting next to each field in the source.
Types ¶
type Config ¶
type Config struct {
// ListenAddr is the address to listen on (e.g., ":8081")
ListenAddr string
// Pricing is the model pricing table used by /v1/sessions/summary to
// compute per-session cost. When nil, sessions.DefaultPricing() is used.
Pricing sessions.PricingTable
// EnableWebUI serves the minimal browser UI at /. It is disabled by default
// so API-only servers do not expose a human-facing development UI unless
// explicitly requested.
EnableWebUI bool
// ContractVersions is the set of tapes contracts this server serves. A
// cassette whose depends.core falls outside the set is refused at
// admission, and the newest entry is what the discovery document
// advertises as current. Empty means DefaultContractVersions().
ContractVersions []cassette.ContractVersion
}
Config is the API server configuration.
type Discovery ¶ added in v0.30.0
type Discovery struct {
ContractVersion string `json:"contract_version"`
Cassettes []DiscoveryEntry `json:"cassettes"`
Problems []cassetterunner.Rejection `json:"problems"`
}
Discovery is the document served at GET /v1/cassettes.
It publishes what each cassette *is* — never what it is configured to. Core holds no configuration values—the deployment supplies them directly to the cassette—so there is nothing here to leak.
type DiscoveryDepends ¶ added in v0.30.0
DiscoveryDepends is a cassette's declared dependency on core.
type DiscoveryEntry ¶ added in v0.30.0
type DiscoveryEntry struct {
Name string `json:"name"`
Version string `json:"version,omitempty"`
DisplayName string `json:"display_name,omitempty"`
Description string `json:"description,omitempty"`
// Audience is the clients that should offer this cassette, empty meaning
// all of them. Published because the filtering happens in the client, and a
// client cannot filter on a field it never receives.
Audience []string `json:"audience"`
RoutePrefix string `json:"route_prefix"`
Depends *DiscoveryDepends `json:"depends,omitempty"`
Tables []string `json:"tables"`
Config []DiscoverySetting `json:"config"`
OpenAPIPath string `json:"openapi_path"`
OpenAPIStatus tapesoapi.Status `json:"openapi_status"`
ManifestDigest string `json:"manifest_digest"`
}
DiscoveryEntry describes one served cassette.
The OpenAPI document is referenced, not inlined. A single spec runs to tens of kilobytes and clients poll discovery; inlining five of them turns every client boot into a megabyte of mostly-unchanged bytes. The digest is enough to know whether the fetch is worth making.
type DiscoverySetting ¶ added in v0.30.0
type DiscoverySetting struct {
Key string `json:"key"`
Type string `json:"type"`
Required bool `json:"required"`
Secret bool `json:"secret"`
Default any `json:"default,omitempty"`
Description string `json:"description,omitempty"`
}
DiscoverySetting is one configuration key as a schema, never as a value.
type MCPError ¶ added in v0.30.0
type MCPError struct {
// Code is the JSON-RPC error code.
Code int `json:"code" oas:"example=-32600"`
// Message is a short description of the failure.
Message string `json:"message" oas:"example=invalid request"`
}
MCPError is a JSON-RPC 2.0 error object.
type MCPRequest ¶ added in v0.30.0
type MCPRequest struct {
// JSONRPC is the protocol version, always "2.0".
JSONRPC string `json:"jsonrpc" oas:"example=2.0"`
// ID correlates a response with this request. Absent on notifications.
ID string `json:"id,omitempty" oas:"example=1"`
// Method is the MCP method being invoked, such as tools/call.
Method string `json:"method" oas:"example=tools/call"`
// Params are the method's arguments.
Params map[string]any `json:"params,omitempty"`
}
MCPRequest is a JSON-RPC 2.0 request to the streamable MCP endpoint.
type MCPResponse ¶ added in v0.30.0
type MCPResponse struct {
// JSONRPC is the protocol version, always "2.0".
JSONRPC string `json:"jsonrpc" oas:"example=2.0"`
// ID is the id of the request this answers.
ID string `json:"id,omitempty" oas:"example=1"`
// Result is the method's return value on success.
Result map[string]any `json:"result,omitempty"`
// Error describes the failure when the call did not succeed.
Error *MCPError `json:"error,omitempty"`
}
MCPResponse is a JSON-RPC 2.0 response from the streamable MCP endpoint.
Exactly one of Result and Error is set, which is the JSON-RPC contract rather than anything this server adds.
type MainUsage ¶ added in v0.25.0
type MainUsage struct {
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
}
MainUsage is the task token slice of a trace: the main agent and its subagents (call_kind=main across every thread), no cache split or cost (those live on the total Usage). Deliberately not spine-only — a subagent doing the user's work is task spend, not shadow.
type Metrics ¶ added in v0.7.0
type Metrics struct {
// contains filtered or unexported fields
}
Metrics is the Prometheus surface for the Tapes API server. Each Server owns its own registry so tests can scrape in isolation; the production path mounts /metrics on the Fiber app via NewServer.
func NewMetrics ¶ added in v0.7.0
func NewMetrics() *Metrics
NewMetrics constructs the Tapes API server's RED metrics. Labels stay templated (`route`) rather than per-URL so :hash path params don't blow up cardinality.
func (*Metrics) Handler ¶ added in v0.7.0
Handler returns a Fiber handler that serves Prometheus text exposition from this Metrics instance's registry. Mount it at /metrics with no auth. The handler is built once at NewMetrics time and cached — see the scrapeHandler field comment for why.
func (*Metrics) Middleware ¶ added in v0.7.0
Middleware returns a Fiber handler that records request count + duration per (route template, method, status). Templates like /v1/sessions/:hash stay as the label value so the :hash path param never expands cardinality.
Register this OUTSIDE recover.New() (i.e. via app.Use before recover) — see resolveStatus for why.
func (*Metrics) Registry ¶ added in v0.7.0
func (m *Metrics) Registry() *prometheus.Registry
Registry exposes the *prometheus.Registry so tests can scrape against the same registry the middleware writes to.
type ModelUsage ¶ added in v0.16.0
type ModelUsage struct {
Model string `json:"model"`
Calls int64 `json:"calls"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CostUsd float64 `json:"cost_usd"`
}
ModelUsage is one model's contribution to a session in the API: how many llm calls ran on it and what they spent. Cost-weighted (priced at derive time) so a per-model share reflects spend, not call count.
type PayloadMode ¶ added in v0.16.0
type PayloadMode string
PayloadMode selects how much span payload a trace response carries. Full embeds the stored content verbatim; preview truncates long text so list-shaped reads stay O(structure), with the span drill-in endpoint serving the full payload on demand.
const ( PayloadFull PayloadMode = "full" PayloadPreview PayloadMode = "preview" )
type RawTurnHeaderItem ¶ added in v0.16.0
type RawTurnHeaderItem struct {
ID int64 `json:"id"`
Source string `json:"source"`
Provider string `json:"provider,omitempty"`
AgentName string `json:"agent_name,omitempty"`
RequestID string `json:"request_id,omitempty"`
ReceivedAt time.Time `json:"received_at"`
Meta json.RawMessage `json:"meta,omitempty" oas:"type=object"`
RequestBytes int64 `json:"request_bytes"`
ResponseBytes int64 `json:"response_bytes"`
}
RawTurnHeaderItem is one wire-log row: what crossed the wire (or arrived as a transcript push), without the payload blobs. The `source` field is the wire-vs-transcript distinction.
type RawTurnListResponse ¶ added in v0.16.0
type RawTurnListResponse struct {
Items []RawTurnHeaderItem `json:"items"`
}
RawTurnListResponse is a session's wire log.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the API server for managing and querying the Tapes system
func NewServer ¶
NewServer creates a new API server. The storer is injected to allow sharing with other components (e.g., the proxy when not run as a singleton).
func (*Server) OpenAPIParser ¶ added in v0.30.0
OpenAPIParser returns the live parser every route on this server registered itself into.
It is the single source the published contract is generated from, which is what makes "served but undocumented" impossible by construction rather than by a convention someone has to remember.
func (*Server) RefreshCassetteSpecs ¶ added in v0.30.0
RefreshCassetteSpecs refreshes this server's cassette OpenAPI cache once.
func (*Server) RunWithListener ¶
RunWithListener starts the API server using the provided listener.
func (*Server) SetCassetteSources ¶ added in v0.30.0
SetCassetteSources configures exact full OpenAPI document URLs on this server's lifetime-owned runner.
func (*Server) StartCassetteSpecRefresh ¶ added in v0.30.0
StartCassetteSpecRefresh begins this server's source-resolution lifecycle. It retries quickly during startup so sidecars can become ready alongside tapes, then settles onto the configured refresh interval.
type SessionDetailResponse ¶ added in v0.12.0
type SessionDetailResponse struct {
Session SessionItem `json:"session"`
}
SessionDetailResponse is the response for GET /v1/sessions/:id: the session record alone. The conversation content lives on the span model (GET /v1/sessions/:id/traces).
type SessionItem ¶ added in v0.12.0
type SessionItem struct {
// Identity — capture-side facts, ingest-written.
ID string `json:"id"`
HarnessID string `json:"harness_id"`
HarnessSessionID string `json:"harness_session_id"`
Cwd string `json:"cwd,omitempty"`
HarnessVersion string `json:"harness_version,omitempty"`
ParentSessionID string `json:"parent_session_id,omitempty"`
StartedAt time.Time `json:"started_at"`
LastSeenAt time.Time `json:"last_seen_at"`
EndedAt *time.Time `json:"ended_at,omitempty"`
HarnessMetadata map[string]any `json:"harness_metadata,omitempty"`
// AuthSubject is the gateway-stamped JWT subject (WorkOS user id)
// captured at ingest; empty for rows captured before the edge began
// stamping it.
AuthSubject string `json:"auth_subject,omitempty"`
// Name is the harness identity-row label — the harness-supplied session
// name (a plan slug), or the folded title (rollup.title) as a fallback
// when no name was captured. This is capture/deriver provenance, NOT a
// user title: ingest re-sends it every turn. Clients should render
// DisplayTitle, not Name (PCC-970).
Name string `json:"name,omitempty"`
// DisplayName is the user's Console rename (sessions.display_name),
// empty unless a user set one. Written only by PATCH /v1/sessions/:id,
// never by ingest, so it survives a live session. It is the top of the
// DisplayTitle resolution; exposed raw so the edit affordance can seed
// its input from the user's own title (not the resolved fallback).
DisplayName string `json:"display_name,omitempty"`
// DisplayTitle is the server-resolved label clients should render:
// DisplayName -> rollup.title (generated) -> preview -> Name -> id
// slice. Resolving once on the server keeps every client (Console,
// paper CLI) from re-deriving — and diverging on — the precedence
// (PCC-970). Never empty: it falls back to a short harness id slice, then
// the session id (the primary key, always set for a stored row).
DisplayTitle string `json:"display_title"`
// Live is a runtime presence signal, not a projection fact: true when
// the session has no recorded end and was seen within the liveness
// window. Keyed on ended_at + last_seen_at recency (both ingest-fresh),
// never on the derived status: an interactive session folds to a
// terminal status (an end_turn assistant reply reads as "completed")
// after every turn while still open, so status cannot gate liveness.
// Computed at response time so the console renders it directly instead
// of inferring "running" itself.
Live bool `json:"live"`
// Rollup is the deriver-owned projection over the session's spans.
Rollup SessionRollup `json:"rollup"`
}
SessionItem is the per-session shape: capture identity at the top level, the deriver-owned projection nested under `rollup`. The split mirrors the storage rows — identity is ingest-written, rollup is deriver-written — so the wire can't blur which layer owns a field.
type SessionListResponse ¶ added in v0.4.0
type SessionListResponse struct {
Items []SessionItem `json:"items"`
NextCursor string `json:"next_cursor,omitempty"`
}
SessionListResponse is the response envelope for GET /v1/sessions.
type SessionRollup ¶ added in v0.25.0
type SessionRollup struct {
Status string `json:"status"`
// Title is the deriver's folded session title (derived_title),
// generated from the conversation. Empty until title generation
// produces one. It never falls back to the identity-row name, so it is
// the stable descriptive title clients prefer for display; the
// identity-row label (harness name or rename) is SessionItem.Name.
Title string `json:"title,omitempty"`
Preview string `json:"preview,omitempty"`
TurnCount int `json:"turn_count"`
// Model is the dominant conversation-spine model; ModelUsage is the
// per-model spend breakdown across every thread (subagent models
// included), cost-ordered so the UI can show "dominant model + share"
// without a cheap-subagent fan-out skewing it.
Model string `json:"model,omitempty"`
ModelUsage []ModelUsage `json:"model_usage,omitempty"`
// KindCounts (spans per call_kind) and Tasks (TaskCreate/TaskUpdate
// folds) are pinned so the rollup shape is uniform across sessions.
KindCounts map[string]int `json:"kind_counts"`
Tasks []TreeTask `json:"tasks"`
Usage SessionUsage `json:"usage"`
}
SessionRollup is the deriver-owned session projection — status, title, counts, and spend, all folded from the span layer at derive time. Every field is 'unknown'/zero/empty until the session first derives.
type SessionTracesResponse ¶ added in v0.16.0
type SessionTracesResponse struct {
Schema string `json:"schema"`
Session SessionItem `json:"session"`
Traces []TraceDetail `json:"traces"`
Links []SpanLinkItem `json:"links"`
}
SessionTracesResponse is the composite session view on the span model. `schema` stamps the projection generation the rows were derived against, so the presentational shape can version independently.
func BuildSessionTraces ¶ added in v0.16.0
func BuildSessionTraces( session SessionItem, turns []storage.SpanTurnRecord, spans []storage.SpanRecord, links []storage.SpanLinkRecord, mode PayloadMode, ) *SessionTracesResponse
BuildSessionTraces assembles the composite response. Pure rendering: every edge and kind here was computed by the deriver. Exported so `tapes dev trace-fixtures` emits byte-identical JSON to the handler.
type SessionUsage ¶ added in v0.25.0
type SessionUsage struct {
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CostUSD float64 `json:"cost_usd"`
}
SessionUsage is the session's total token/cost spend, folded from the span layer. Pinned (no omitempty) for a uniform object shape.
type SpanItem ¶ added in v0.16.0
type SpanItem struct {
TraceID string `json:"trace_id"`
SpanID string `json:"span_id"`
ParentSpanID string `json:"parent_span_id,omitempty"`
// Seq is the span's presentation ordinal within its trace; spans
// arrive sorted by it (started_at ties inside one llm call — parallel
// tool batches share an instant).
Seq int64 `json:"seq"`
Kind string `json:"kind"`
Name string `json:"name"`
Status string `json:"status"`
StartedAt time.Time `json:"started_at"`
DurationNS int64 `json:"duration_ns"`
// Deriver-written taxonomy, promoted from the old metadata grab-bag.
CallKind string `json:"call_kind"`
Model string `json:"model"`
StopReason string `json:"stop_reason"`
ThreadID string `json:"thread_id"`
RawTurnID int64 `json:"raw_turn_id,omitempty"`
// Verdict is the typed security-monitor disposition (null off
// permission-check spans), deriver-written. It is a Verdict object or
// null on the wire; the oas tag states that, because a json.RawMessage
// carries no shape a reflector could recover.
Verdict json.RawMessage `json:"verdict" oas:"type=object,nullable"`
// Input/Output are content-block arrays (llm.ContentBlock), uniform for
// every kind (tool spans included — no unwrapping). Pinned to [] when
// empty.
Input json.RawMessage `json:"input" oas:"type=array:object"`
Output json.RawMessage `json:"output" oas:"type=array:object"`
// Usage (was `metrics`) is an llm.Usage object on the wire — {}-pinned
// for usage-less spans.
Usage json.RawMessage `json:"usage" oas:"type=object"`
// Payload marks a preview-truncated span so the console drills in for
// the full payload; absent in full mode.
Payload string `json:"payload,omitempty"`
}
SpanItem is one observed unit of work. Every field is a deriver output, formatting-only: the harness-taxonomy fields (call_kind, model, stop_reason, thread_id, verdict) are typed rather than bagged in a metadata map, and input/output are uniform content-block arrays for ALL kinds — the console owns per-kind rendering.
type SpanLinkItem ¶ added in v0.16.0
type SpanLinkItem struct {
Kind string `json:"kind"`
FromTraceID string `json:"from_trace_id"`
FromSpanID string `json:"from_span_id"`
FromIO string `json:"from_io,omitempty"`
ToTraceID string `json:"to_trace_id"`
ToSpanID string `json:"to_span_id"`
ToIO string `json:"to_io,omitempty"`
}
SpanLinkItem is a dataflow edge. kind is a typed top-level field (rejoin / verdict / compaction-seam / emits / feeds); from/to trace ids differ on cross-trace causality.
type StatsResponse ¶ added in v0.4.0
type StatsResponse struct {
SessionCount int `json:"session_count"`
TurnCount int `json:"turn_count"`
CompletedCount int `json:"completed_count"`
TotalCost float64 `json:"total_cost"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
TotalDurationMs int64 `json:"total_duration_ms"`
ToolCalls int `json:"tool_calls"`
}
StatsResponse is the response for GET /v1/stats.
The numbers come from the span-projection trace-grain rollups, so they agree with the session detail and trace views:
- InputTokens / OutputTokens / TotalCost are SUMs of span_turns rollups — delta-only per-call usage, never the re-sent history (each main call re-bills the whole conversation on the wire).
- TotalDurationMs is the SUM of trace durations — agent time. Idle time between turns does not count. Served in milliseconds, not the nanoseconds we store: the summed ns over a wide window overflows a JSON consumer's 2^53 safe-integer range (~104 cumulative days), and sub-ms precision is meaningless for an aggregate agent-time figure.
- TurnCount counts traces (user-visible turns).
- ToolCalls is the SUM of the turn rollups' tool span counts, windowed on the turn's started_at like every other figure here rather than on each tool span's own timestamp (PCC-936).
- CompletedCount counts distinct sessions whose denormalized derived_status is 'completed' (chain-aware, PCC-515).
type TraceDetail ¶ added in v0.16.0
type TraceDetail struct {
Schema string `json:"schema,omitempty"`
Trace TraceItem `json:"trace"`
Spans []SpanItem `json:"spans"`
Links []SpanLinkItem `json:"links,omitempty"`
}
TraceDetail is one trace with its spans. In the composite session response links are session-scoped (top level); the single-trace endpoint sets Links to the edges touching that trace. `schema` stamps the projection generation on the STANDALONE /v1/traces/{id} response (omitempty — the composite embeds TraceDetail and already carries one stamp at the top level, so the embedded copies stay unstamped).
func BuildTraceDetail ¶ added in v0.16.0
func BuildTraceDetail(turn storage.SpanTurnRecord, spans []storage.SpanRecord, links []storage.SpanLinkRecord, mode PayloadMode) TraceDetail
BuildTraceDetail renders one turn with its spans and links. Exported so `tapes dev trace-fixtures` emits byte-identical JSON to the handler.
type TraceItem ¶ added in v0.16.0
type TraceItem struct {
TraceID string `json:"trace_id"`
// UserPrompt is served explicitly (not omitempty): a synthetic opener
// has an empty prompt, and dropping the key turns the empty string
// into `undefined` on the wire, which breaks consumers that expect a
// string (e.g. the console's stripHarnessTags). Empty means synthetic.
UserPrompt string `json:"user_prompt"`
// ResponsePreview is the derive-time fold of the closing
// conversation-spine llm call's text output — the answer line for
// collapsed turn cards, so summary consumers never need spans.
ResponsePreview string `json:"response_preview,omitempty"`
Status string `json:"status"`
// Source is the capture origin of the turn's rows ("wire" |
// "transcript"), promoted from raw_turns.source. Per-trace, so a
// session can mix live wire capture and transcript backfill. Today
// every trace is "wire": transcripts only reconcile fork/parent edges
// during derivation, they never form a trace on their own. "transcript"
// becomes real when a session is reconstructed purely from a transcript
// file with no proxy capture (an OSS backfill path).
Source string `json:"source"`
StartedAt time.Time `json:"started_at"`
EndedAt *time.Time `json:"ended_at,omitempty"`
DurationNS int64 `json:"duration_ns"`
SpanCount int `json:"span_count"`
// Usage is the trace's total token/cost spend over ALL llm spans,
// shadow calls included; MainUsage is the task slice — the main agent
// and its subagents (every call_kind=main span, across threads). The
// difference (Usage − MainUsage) is the harness's shadow spend
// (permission checks, title-gen, web summaries) on the turn.
Usage TraceUsage `json:"usage"`
MainUsage MainUsage `json:"main_usage"`
// Synthetic is a typed deriver signal ("post-compaction" for a
// compaction continuation, "shadow-opener" for a shadow-only opener),
// promoted out of the old metadata grab-bag. Absent for genuine
// prompt-opened turns.
Synthetic string `json:"synthetic,omitempty"`
}
TraceItem is one user-visible turn's header. session_id / harness ids are not duplicated here — they belong to the session. A trace's post-compaction status is the typed Synthetic field below (promoted out of the old metadata grab-bag); the same seam is also recoverable from the session's compaction-seam links.
type TraceListResponse ¶ added in v0.16.0
TraceListResponse is the summaries list for one session. `schema` stamps the projection generation the rows were derived against — the same stamp the composite carries — so every trace-grain response is self-describing, not just the composite.
func BuildTraceList ¶ added in v0.16.0
func BuildTraceList(rows []storage.TraceSummaryRecord) TraceListResponse
BuildTraceList renders the turn-summary rows for one session. Exported so `tapes dev trace-fixtures` emits byte-identical JSON to the handler.
type TraceUsage ¶ added in v0.25.0
type TraceUsage struct {
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CacheReadTokens int64 `json:"cache_read_tokens"`
CacheCreationTokens int64 `json:"cache_creation_tokens"`
CostUSD float64 `json:"cost_usd"`
}
TraceUsage is a trace's total token/cost rollup. Fields are pinned (no omitempty) so the object shape is uniform across traces.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package cassetterunner resolves and serves the cassettes an API server publishes.
|
Package cassetterunner resolves and serves the cassettes an API server publishes. |
|
Package mcp provides an MCP (Model Context Protocol) server for the Tapes system.
|
Package mcp provides an MCP (Model Context Protocol) server for the Tapes system. |