transcript

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Dec 26, 2025 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package transcript provides recording and management of AI conversation transcripts.

Core types:

  • Transcript: A recorded conversation with metadata and turns
  • Turn: A single message in a conversation (user, assistant, or tool)
  • Manager: Interface for transcript lifecycle management
  • FileStore: File-based transcript storage implementation
  • Searcher: Grep-based transcript search
  • Viewer: Transcript display and export

Example usage:

store := transcript.NewFileStore(transcript.StoreConfig{
    BaseDir: ".devflow/runs",
})
err := store.StartRun("run-123", transcript.RunMetadata{
    FlowID: "ticket-to-pr",
})
err = store.RecordTurn("run-123", transcript.Turn{
    Role:    "assistant",
    Content: "I'll implement this feature...",
})

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrRunNotFound      = errors.New("run not found")
	ErrRunAlreadyExists = errors.New("run already exists")
	ErrRunNotStarted    = errors.New("run not started")
	ErrRunAlreadyEnded  = errors.New("run already ended")
)

Errors

Functions

This section is empty.

Types

type FileStore

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

FileStore stores transcripts as files

func NewFileStore

func NewFileStore(config StoreConfig) (*FileStore, error)

NewFileStore creates a file-based transcript store

func (*FileStore) AddCost

func (s *FileStore) AddCost(runID string, cost float64) error

AddCost adds cost to an active transcript

func (*FileStore) BaseDir

func (s *FileStore) BaseDir() string

BaseDir returns the base directory for the store

func (*FileStore) Delete

func (s *FileStore) Delete(runID string) error

Delete removes a run

func (*FileStore) EndRun

func (s *FileStore) EndRun(runID string, status RunStatus) error

EndRun completes a transcript

func (*FileStore) EndRunWithError

func (s *FileStore) EndRunWithError(runID string, err error) error

EndRunWithError completes a transcript with an error

func (*FileStore) GetActive

func (s *FileStore) GetActive(runID string) (*Transcript, bool)

GetActive returns an active transcript (for monitoring)

func (*FileStore) List

func (s *FileStore) List(filter ListFilter) ([]Meta, error)

List returns metadata for runs matching filter

func (*FileStore) ListActive

func (s *FileStore) ListActive() []string

ListActive returns all active run IDs

func (*FileStore) Load

func (s *FileStore) Load(runID string) (*Transcript, error)

Load retrieves a complete transcript

func (*FileStore) LoadMetadata

func (s *FileStore) LoadMetadata(runID string) (*Meta, error)

LoadMetadata retrieves just the metadata

func (*FileStore) RecordToolCall

func (s *FileStore) RecordToolCall(runID string, tc ToolCall) error

RecordToolCall adds a tool call to the last turn of an active transcript

func (*FileStore) RecordTurn

func (s *FileStore) RecordTurn(runID string, turn Turn) error

RecordTurn adds a turn to an active transcript

func (*FileStore) StartRun

func (s *FileStore) StartRun(runID string, meta RunMetadata) error

StartRun begins a new transcript

type ListFilter

type ListFilter struct {
	FlowID string
	Status RunStatus
	After  time.Time
	Before time.Time
	Limit  int
}

ListFilter filters transcript listing

type Manager

type Manager interface {
	// Lifecycle
	StartRun(runID string, metadata RunMetadata) error
	RecordTurn(runID string, turn Turn) error
	EndRun(runID string, status RunStatus) error

	// Retrieval
	Load(runID string) (*Transcript, error)
	LoadMetadata(runID string) (*Meta, error)
	List(filter ListFilter) ([]Meta, error)

	// Maintenance
	Delete(runID string) error
}

Manager is the interface for transcript operations

type Meta

type Meta struct {
	RunID          string         `json:"runId,omitempty"`
	FlowID         string         `json:"flowId"`
	NodeID         string         `json:"nodeId,omitempty"`
	Input          map[string]any `json:"input,omitempty"`
	StartedAt      time.Time      `json:"startedAt"`
	EndedAt        time.Time      `json:"endedAt,omitempty"`
	Status         RunStatus      `json:"status"`
	TotalTokensIn  int            `json:"totalTokensIn"`
	TotalTokensOut int            `json:"totalTokensOut"`
	TotalCost      float64        `json:"totalCost"`
	TurnCount      int            `json:"turnCount"`
	Error          string         `json:"error,omitempty"`
}

Meta contains run metadata

type RunMetadata

type RunMetadata struct {
	FlowID string
	NodeID string
	Input  map[string]any
}

RunMetadata is input for starting a new run

type RunStatus

type RunStatus string

RunStatus indicates the status of a run

const (
	RunStatusRunning   RunStatus = "running"
	RunStatusCompleted RunStatus = "completed"
	RunStatusFailed    RunStatus = "failed"
	RunStatusCanceled  RunStatus = "canceled"
)

type SearchOptions

type SearchOptions struct {
	CaseSensitive bool
	MaxResults    int
	Context       int // Lines of context around match
}

SearchOptions configures content search

type SearchResult

type SearchResult struct {
	RunID     string `json:"runId"`
	TurnID    int    `json:"turnId,omitempty"`
	Role      string `json:"role,omitempty"`
	Content   string `json:"content"`
	MatchLine int    `json:"matchLine,omitempty"`
	Match     string `json:"match,omitempty"`
}

SearchResult represents a search match

type Searcher

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

Searcher provides search capabilities over transcripts

func NewSearcher

func NewSearcher(baseDir string) *Searcher

NewSearcher creates a searcher

func (*Searcher) FindByDateRange

func (s *Searcher) FindByDateRange(start, end time.Time) ([]Meta, error)

FindByDateRange returns transcripts in date range

func (*Searcher) FindByFlow

func (s *Searcher) FindByFlow(flowID string) ([]Meta, error)

FindByFlow returns transcripts for a flow

func (*Searcher) FindByStatus

func (s *Searcher) FindByStatus(status RunStatus) ([]Meta, error)

FindByStatus returns transcripts with status

func (*Searcher) FindByTokenRange

func (s *Searcher) FindByTokenRange(minIn, maxIn, minOut, maxOut int) ([]Meta, error)

FindByTokenRange returns transcripts within token ranges

func (*Searcher) RunStats

func (s *Searcher) RunStats(filter ListFilter) (*Statistics, error)

RunStats returns statistics for matching runs

func (*Searcher) SearchContent

func (s *Searcher) SearchContent(query string, opts SearchOptions) ([]SearchResult, error)

SearchContent searches transcript content using ripgrep or grep

func (*Searcher) TotalCost

func (s *Searcher) TotalCost(filter ListFilter) (float64, error)

TotalCost calculates total cost for matching runs

func (*Searcher) TotalTokens

func (s *Searcher) TotalTokens(filter ListFilter) (int, int, error)

TotalTokens calculates total tokens for matching runs

type Statistics

type Statistics struct {
	TotalRuns      int
	CompletedRuns  int
	FailedRuns     int
	CanceledRuns   int
	ActiveRuns     int
	TotalTokensIn  int
	TotalTokensOut int
	TotalCost      float64
	AvgTokensIn    int
	AvgTokensOut   int
	AvgCost        float64
}

Statistics holds aggregated run statistics

type StoreConfig

type StoreConfig struct {
	BaseDir string
}

StoreConfig holds configuration for transcript storage

type ToolCall

type ToolCall struct {
	ID     string         `json:"id,omitempty"`
	Name   string         `json:"name"`
	Input  map[string]any `json:"input"`
	Output string         `json:"output,omitempty"`
	Error  string         `json:"error,omitempty"`
}

ToolCall represents a tool/function call

type Transcript

type Transcript struct {
	RunID    string `json:"runId"`
	Metadata Meta   `json:"metadata"`
	Turns    []Turn `json:"turns"`
}

Transcript represents a complete conversation record

func Load

func Load(baseDir, runID string) (*Transcript, error)

Load loads a transcript from disk

func NewTranscript

func NewTranscript(runID, flowID string) *Transcript

NewTranscript creates a new transcript

func (*Transcript) AddCost

func (t *Transcript) AddCost(cost float64)

AddCost adds to the total cost

func (*Transcript) AddToolCall

func (t *Transcript) AddToolCall(name string, input map[string]any, output string)

AddToolCall adds a tool call to the last assistant turn

func (*Transcript) AddToolCallError

func (t *Transcript) AddToolCallError(name string, input map[string]any, err error)

AddToolCallError adds a failed tool call

func (*Transcript) AddTurn

func (t *Transcript) AddTurn(role, content string, tokens int) *Turn

AddTurn adds a turn to the transcript

func (*Transcript) AddTurnWithDetails

func (t *Transcript) AddTurnWithDetails(turn Turn) *Turn

AddTurnWithDetails adds a turn with full control over fields

func (*Transcript) Cancel

func (t *Transcript) Cancel()

Cancel marks the transcript as canceled

func (*Transcript) Complete

func (t *Transcript) Complete()

Complete marks the transcript as completed

func (*Transcript) Duration

func (t *Transcript) Duration() time.Duration

Duration returns the run duration

func (*Transcript) Fail

func (t *Transcript) Fail(err error)

Fail marks the transcript as failed

func (*Transcript) IsActive

func (t *Transcript) IsActive() bool

IsActive returns true if the run is still in progress

func (*Transcript) LastTurn

func (t *Transcript) LastTurn() *Turn

LastTurn returns the last turn or nil

func (*Transcript) Save

func (t *Transcript) Save(baseDir string) error

Save writes the transcript to disk

func (*Transcript) SetCost

func (t *Transcript) SetCost(cost float64)

SetCost sets the total cost

func (*Transcript) TurnsByRole

func (t *Transcript) TurnsByRole(role string) []Turn

TurnsByRole returns all turns with the given role

type Turn

type Turn struct {
	ID         int        `json:"id"`
	Role       string     `json:"role"` // system, user, assistant, tool_result
	Content    string     `json:"content"`
	TokensIn   int        `json:"tokensIn,omitempty"`
	TokensOut  int        `json:"tokensOut,omitempty"`
	Timestamp  time.Time  `json:"timestamp"`
	ToolCalls  []ToolCall `json:"toolCalls,omitempty"`
	DurationMs int64      `json:"durationMs,omitempty"`
}

Turn represents a conversation turn

type Viewer

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

Viewer displays transcripts

func NewViewer

func NewViewer(colorEnabled bool) *Viewer

NewViewer creates a viewer

func (*Viewer) Diff

func (v *Viewer) Diff(w io.Writer, a, b *Transcript) error

Diff compares two transcripts

func (*Viewer) ExportJSON

func (v *Viewer) ExportJSON(w io.Writer, t *Transcript) error

ExportJSON exports to JSON format

func (*Viewer) ExportMarkdown

func (v *Viewer) ExportMarkdown(w io.Writer, t *Transcript) error

ExportMarkdown exports to markdown format

func (*Viewer) FormatMetaList

func (v *Viewer) FormatMetaList(w io.Writer, metas []Meta) error

FormatMetaList formats a list of metadata for display

func (*Viewer) FormatStats

func (v *Viewer) FormatStats(w io.Writer, stats *Statistics) error

FormatStats formats statistics for display

func (*Viewer) ViewAssistantOnly

func (v *Viewer) ViewAssistantOnly(w io.Writer, t *Transcript) error

ViewAssistantOnly displays only assistant turns

func (*Viewer) ViewFull

func (v *Viewer) ViewFull(w io.Writer, t *Transcript) error

ViewFull displays the complete transcript

func (*Viewer) ViewSummary

func (v *Viewer) ViewSummary(w io.Writer, t *Transcript) error

ViewSummary displays a brief summary

func (*Viewer) ViewTurn

func (v *Viewer) ViewTurn(w io.Writer, turn Turn) error

ViewTurn displays a single turn

Jump to

Keyboard shortcuts

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