opencode

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package opencode reads the sessions of OpenCode, the TypeScript coding agent (anomalyco/opencode, formerly sst/opencode), in each of the three ways it has stored them under its data directory, ~/.local/share/opencode:

  • G1, up to 1.1.65: the storage/ tree, one JSON file per session, message and part (Tree);
  • G2, 1.2.0 to 1.19: the V1 tables of opencode.db, session, message and part, whose rows hold the same JSON;
  • G3, 2.0.0 on: the V2 tables of the same database, session_v2 and session_message, one row per message.

It imports the standard library alone, so it does not open a database itself: the opencode/sqlite package opens one and yields its rows as this package's types, through the Store interface the storage tree implements too. Not read here: Crush, the Go program once named opencode (opencode-ai/opencode), whose .opencode/opencode.db holds another schema; OpenCode 2's preview opencode-next.db; and the layout OpenCode wrote before its MessageV2 model, project/<dir>/storage/session, which Tree.Legacy lists.

Every object keeps the members it does not declare and writes them back, so a record decoded and encoded again is the same JSON value. A record that cannot be read is a Stray, never an error. The package does not interpret: rebuilding what each request sent, and converting to the Agent Session Format, are the convert subpackage's; docs/formats/opencode.md is the mapping.

Index

Constants

View Source
const (
	DirStorage = "storage"
	DirSession = "session"
	DirMessage = "message"
	DirPart    = "part"
	DirProject = "project"
	// DatabaseName is the database OpenCode 1.2 and later keep in the
	// data directory.
	DatabaseName = "opencode.db"
)

Directory names of a data directory and its storage/ tree.

View Source
const (
	RoleUser      = "user"
	RoleAssistant = "assistant"
)

Message roles of the V1 model.

View Source
const (
	PartText       = "text"
	PartReasoning  = "reasoning"
	PartFile       = "file"
	PartAgent      = "agent"
	PartCompaction = "compaction"
	PartSubtask    = "subtask"
	PartRetry      = "retry"
	PartStepStart  = "step-start"
	PartStepFinish = "step-finish"
	PartSnapshot   = "snapshot"
	PartPatch      = "patch"
	PartTool       = "tool"
)

Part types of the V1 model, MessageV2.Part.

View Source
const (
	ToolPending   = "pending"
	ToolRunning   = "running"
	ToolCompleted = "completed"
	ToolError     = "error"
)

Tool states of a V1 tool part.

View Source
const (
	TypeUser             = "user"
	TypeSynthetic        = "synthetic"
	TypeSystem           = "system"
	TypeSkill            = "skill"
	TypeShell            = "shell"
	TypeAssistant        = "assistant"
	TypeCompaction       = "compaction"
	TypeAgentSwitched    = "agent-switched"
	TypeModelSwitched    = "model-switched"
	TypeLocationSwitched = "location-switched"
	TypeIdle             = "idle"
)

Types of a V2 session_message row, SessionMessage.Info.

View Source
const (
	CompactionRunning   = "running"
	CompactionCompleted = "completed"
	CompactionFailed    = "failed"
)

Compaction statuses of V2.

View Source
const (
	ContentText      = "text"
	ContentReasoning = "reasoning"
	ContentTool      = "tool"
)

Assistant content types of V2.

View Source
const (
	Tool2Streaming = "streaming"
	Tool2Running   = "running"
	Tool2Completed = "completed"
	Tool2Error     = "error"
)

Tool states of V2.

View Source
const (
	ErrorAborted = "MessageAbortedError"
)

Assistant error names of the V1 model.

Variables

KnownParts lists the part types OpenCode's V1 model defines.

KnownTypes lists the row types OpenCode 2 defines.

Functions

func Count

func Count(raw json.RawMessage) int

Count reads a token count: a non-negative integer, else 0.

func Databases

func Databases(dir string) []string

Databases lists the databases of a data directory other than opencode.db: those of other channels.

func FindSessions

func FindSessions(root string) ([]string, error)

FindSessions lists the OpenCode stores under root: each data directory, each database of another channel in one, and each database file outside one. A file root is returned as it is. A store is converted whole: OpenCode keeps every session of a data directory in one database or one storage/ tree. Directories that cannot be read are passed over, and symbolic links are not followed.

func Float

func Float(raw json.RawMessage) (float64, bool)

Float reads a JSON number.

func Int

func Int(raw json.RawMessage) (int64, bool)

Int reads a JSON number that is an integer.

func IsDataDir

func IsDataDir(dir string) bool

IsDataDir reports whether dir is an OpenCode data directory, such as ~/.local/share/opencode: it holds opencode.db, or a storage/ tree with sessions.

func IsDatabaseName

func IsDatabaseName(name string) bool

IsDatabaseName reports whether a file name is one OpenCode gives a database: opencode.db, or opencode-<channel>.db for a build of another channel. OpenCode 2's preview database, opencode-next.db, holds another schema and is not one.

func IsKnownPart

func IsKnownPart(t string) bool

IsKnownPart reports whether OpenCode's V1 model defines part type t.

func IsKnownType

func IsKnownType(t string) bool

IsKnownType reports whether OpenCode 2 defines row type t.

func IsNull

func IsNull(raw json.RawMessage) bool

IsNull reports whether raw is absent or null.

func LocationDirectory

func LocationDirectory(raw json.RawMessage) string

LocationDirectory reads a location-switched row's location.directory.

func MetadataBool

func MetadataBool(raw json.RawMessage, name string) bool

MetadataBool reads a boolean member of a metadata object.

func MetadataString

func MetadataString(raw json.RawMessage, name string) string

MetadataString reads a string member of a metadata object.

func Millis

func Millis(raw json.RawMessage) (int64, bool)

Millis reads an epoch-millisecond time, OpenCode's every timestamp, in the range a time.Time holds.

func ShellOutput

func ShellOutput(raw json.RawMessage) string

ShellOutput reads a shell row's output.output.

func SkillText

func SkillText(raw json.RawMessage) (string, bool)

SkillText reads a V2 user message's skill: its text, when it carries one.

func SortMessages

func SortMessages(gen Generation, ms []*MessageRecord)

SortMessages orders a session's messages as OpenCode reads them: G2 by time_created, then ID; G1 by ID, its file name. Each message's parts are ordered by ID.

func StoreOf

func StoreOf(path string) (string, bool)

StoreOf returns the store a path names: the data directory it is, or is in, or else the database file itself. A file of the storage/ tree names its data directory, as does opencode.db.

func Truthy

func Truthy(raw json.RawMessage) bool

Truthy reports whether a JSON value is truthy as JavaScript reads it: absent, null, false, 0 and "" are not.

func Units

func Units(root string) int

Units counts the files of a data directory's storage/ tree that hold a session, a message or a part: every record a conversion of the tree reads, so a test can hold a report's tally to it.

Types

type Cache

type Cache struct {
	Read  json.RawMessage `json:"read"`
	Write json.RawMessage `json:"write"`

	Members
}

Cache is a token count's cache reads and writes.

func (Cache) MarshalJSON

func (c Cache) MarshalJSON() ([]byte, error)

MarshalJSON writes the counts back as they were read.

func (*Cache) UnmarshalJSON

func (c *Cache) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the counts, keeping undeclared members.

type Column

type Column struct {
	Name  string
	Value any
}

Column is one column of a database row: its name and its value as database/sql scans it, an int64, float64, string, []byte or nil.

type Columns

type Columns []Column

Columns is a row of a table, in the table's column order.

func (Columns) Get

func (cs Columns) Get(name string) (any, bool)

Get returns a column's value; false when the row has no such column.

func (Columns) Int

func (cs Columns) Int(name string) (int64, bool)

Int returns an integer column.

func (Columns) JSON

func (cs Columns) JSON() json.RawMessage

JSON writes the row as one JSON object, a member per column in the table's order: a JSON text column as the value it holds when it holds one, text as a string, a number as a number, null as null, and a blob as base64 text.

func (Columns) String

func (cs Columns) String(name string) string

String returns a text column; empty when it is absent, null or not text.

type Content2

type Content2 struct {
	Type                string          `json:"type"`
	Text                string          `json:"text"`
	State               json.RawMessage `json:"state"`
	Time                json.RawMessage `json:"time"`
	ID                  string          `json:"id"`
	Name                string          `json:"name"`
	Executed            bool            `json:"executed"`
	ProviderState       json.RawMessage `json:"providerState"`
	ProviderResultState json.RawMessage `json:"providerResultState"`

	Members
}

Content2 is one item of a V2 assistant's content: text, reasoning or a tool. State is the provider state of text and reasoning, and the ToolState2 of a tool, which Content2.Tool decodes.

func (Content2) MarshalJSON

func (c Content2) MarshalJSON() ([]byte, error)

MarshalJSON writes the item back as it was read.

func (*Content2) ReasoningDone

func (c *Content2) ReasoningDone() bool

ReasoningDone reports whether a reasoning item's time says it completed; an item with no time is taken as completed, as OpenCode reads it.

func (*Content2) Tool

func (c *Content2) Tool() (*ToolState2, error)

Tool decodes a tool item's state.

func (*Content2) UnmarshalJSON

func (c *Content2) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes an item, keeping undeclared members and members of another JSON type.

type Database

type Database interface {
	Store
	Close() error
}

Database is a store read from a database file, open until closed.

type File2

type File2 struct {
	Data        string `json:"data"`
	Mime        string `json:"mime"`
	Name        string `json:"name"`
	Description *string
	Source      struct {
		Type string `json:"type"`
		URI  string `json:"uri"`
	} `json:"source"`
	Mention *struct {
		Text string `json:"text"`
	} `json:"mention"`
}

File2 is a V2 user message's attachment, FileAttachment: base64 data, its mime type, where it came from, and how it was mentioned.

func DecodeFile2

func DecodeFile2(raw json.RawMessage) (File2, bool)

DecodeFile2 reads an attachment; false when it is not an object.

type FileAttachment

type FileAttachment struct {
	Mime     string `json:"mime"`
	Filename string `json:"filename"`
	URL      string `json:"url"`
}

FileAttachment is the file part a completed tool state's attachments hold, or a user message's file part: the members a converter reads.

func Attachment

func Attachment(raw json.RawMessage) (FileAttachment, bool)

Attachment decodes one attachment; false when it is not a file part.

type Fork

type Fork struct {
	Type      string
	MessageID string
}

Fork is a V2 fork's boundary: where the origin's history it copied ends.

type Generation

type Generation int

Generation is one of OpenCode's three ways of storing sessions.

const (
	// G1 is the storage/ tree of JSON files, up to 1.1.65.
	G1 Generation = 1
	// G2 is the V1 tables of opencode.db, session, message and part,
	// from 1.2.0 to 1.19.
	G2 Generation = 2
	// G3 is the V2 tables of opencode.db, session_v2 and
	// session_message, from 2.0.0.
	G3 Generation = 3
)

func (Generation) String

func (g Generation) String() string

String names the generation as the documents do.

type Members

type Members = jsonline.Members

Members is embedded in every object this package decodes. It keeps the members the Go type does not declare, and remembers which declared members the input carried and which were null, so an object decoded and encoded again is the same JSON value.

type Memory

type Memory struct {
	StoreName   string
	SessionList []*Session
	Strays      []*Stray
	// MessagesOf holds each V1 session's messages, by session ID.
	MessagesOf map[string][]*MessageRecord
	// RowsOf and QueueOf hold each V2 session's rows and queued input.
	RowsOf   map[string][]*Row2
	QueueOf  map[string][]*QueueRow
	Projects map[string]Project
	Migrated bool
	// contains filtered or unexported fields
}

Memory is a store held in memory: what a test or a fuzz target builds, or a reader that has its records already.

func (*Memory) Messages

func (m *Memory) Messages(s *Session) ([]*MessageRecord, []*Stray, error)

Messages returns a V1 session's messages, ordered as its generation orders them.

func (*Memory) MigrationDone

func (m *Memory) MigrationDone() bool

MigrationDone reports Migrated.

func (*Memory) Name

func (m *Memory) Name() string

Name names the store in findings.

func (*Memory) Orphans

func (m *Memory) Orphans(map[string]bool) ([]*Stray, error)

Orphans lists the records of sessions no conversion read.

func (*Memory) Project

func (m *Memory) Project(id string) (Project, bool)

Project returns a project.

func (*Memory) Rows

func (m *Memory) Rows(s *Session) ([]*Row2, []*QueueRow, error)

Rows returns a V2 session's rows in seq order.

func (*Memory) Sessions

func (m *Memory) Sessions() ([]*Session, []*Stray, error)

Sessions lists the sessions.

type Message

type Message struct {
	ID        string       `json:"id"`
	SessionID string       `json:"sessionID"`
	Role      string       `json:"role"`
	Time      *MessageTime `json:"time"`

	// A user message's.
	Agent   string          `json:"agent"`
	Model   *ModelRef       `json:"model"`
	System  string          `json:"system"`
	Tools   json.RawMessage `json:"tools"`
	Format  json.RawMessage `json:"format"`
	Variant string          `json:"variant"`
	// Summary is an object on a user message and true on an assistant
	// message that holds a compaction's summary.
	Summary json.RawMessage `json:"summary"`

	// An assistant message's.
	ParentID   string          `json:"parentID"`
	ModelID    string          `json:"modelID"`
	ProviderID string          `json:"providerID"`
	Mode       string          `json:"mode"`
	Path       json.RawMessage `json:"path"`
	Cost       json.RawMessage `json:"cost"`
	Tokens     *Tokens         `json:"tokens"`
	Error      *MessageError   `json:"error"`
	Finish     string          `json:"finish"`
	Structured json.RawMessage `json:"structured"`

	Members
}

Message is a V1 message's info, MessageV2.Info: a user message or an assistant one, told apart by Role. A G1 file holds it whole; a G2 row's data holds it without id and sessionID, which the row's columns carry.

func (*Message) Completed

func (m *Message) Completed() (int64, bool)

Completed is an assistant message's time.completed, in milliseconds.

func (*Message) Created

func (m *Message) Created() (int64, bool)

Created is the message's time.created, in milliseconds.

func (*Message) IsSummary

func (m *Message) IsSummary() bool

IsSummary reports whether an assistant message holds a compaction's summary.

func (Message) MarshalJSON

func (m Message) MarshalJSON() ([]byte, error)

MarshalJSON writes the message back as it was read.

func (*Message) UnmarshalJSON

func (m *Message) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a message, keeping undeclared members and members of another JSON type.

type Message2

type Message2 struct {
	Metadata json.RawMessage `json:"metadata"`
	Time     *Time2          `json:"time"`

	// user, synthetic, system, skill
	Text        string            `json:"text"`
	Description string            `json:"description"`
	Files       []json.RawMessage `json:"files"`
	Agents      json.RawMessage   `json:"agents"`
	Skills      []json.RawMessage `json:"skills"`
	Skill       string            `json:"skill"`
	Name        string            `json:"name"`

	// shell
	ShellID string          `json:"shellID"`
	Command string          `json:"command"`
	Status  string          `json:"status"`
	Exit    json.RawMessage `json:"exit"`
	Output  json.RawMessage `json:"output"`

	// assistant, and the switches
	Agent         string            `json:"agent"`
	Model         *ModelRef         `json:"model"`
	Previous      json.RawMessage   `json:"previous"`
	Content       []json.RawMessage `json:"content"`
	Snapshot      json.RawMessage   `json:"snapshot"`
	Finish        string            `json:"finish"`
	RawFinish     string            `json:"rawFinish"`
	ProviderState json.RawMessage   `json:"providerState"`
	Cost          json.RawMessage   `json:"cost"`
	Tokens        *Tokens           `json:"tokens"`
	Error         *SessionError     `json:"error"`
	Retry         json.RawMessage   `json:"retry"`

	// compaction
	Reason          string          `json:"reason"`
	Summary         string          `json:"summary"`
	Recent          string          `json:"recent"`
	ProviderContext json.RawMessage `json:"providerContext"`

	// location-switched
	Location  json.RawMessage `json:"location"`
	ProjectID string          `json:"projectID"`
	Subpath   string          `json:"subpath"`

	// idle
	Outcome string `json:"outcome"`

	Members
}

Message2 is the data of a V2 session_message row: the message without its id and type, which the row's columns carry. Which members it has depends on the row's type; a member one type declares with another JSON type than another type does is kept raw.

func (Message2) MarshalJSON

func (m Message2) MarshalJSON() ([]byte, error)

MarshalJSON writes the data back as it was read.

func (*Message2) UnmarshalJSON

func (m *Message2) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a row's data, keeping undeclared members and members of another JSON type.

type MessageError

type MessageError struct {
	Name string          `json:"name"`
	Data json.RawMessage `json:"data"`

	Members
}

MessageError is a V1 assistant message's error: a name and its data.

func (MessageError) MarshalJSON

func (e MessageError) MarshalJSON() ([]byte, error)

MarshalJSON writes the error back as it was read.

func (*MessageError) Message

func (e *MessageError) Message() string

Message is the error's data.message, when it has one.

func (*MessageError) UnmarshalJSON

func (e *MessageError) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the error, keeping undeclared members.

type MessageRecord

type MessageRecord struct {
	Unit string
	ID   string
	// Created is when OpenCode orders the message by: the row's
	// time_created (G2), or info's time.created (G1).
	Created int64
	Info    *Message
	// Raw is the message's object as read: a G1 file's contents, or a
	// G2 row's data.
	Raw json.RawMessage
	// Err says why the message could not be read; its parts are then
	// strays.
	Err   error
	Parts []*PartRecord
}

MessageRecord is one V1 message as read, with its parts.

func DecodeMessage

func DecodeMessage(unit, id, sessionID string, created int64, data []byte) *MessageRecord

DecodeMessage reads a V1 message: a G1 file's contents, or a G2 row's data with the row's id and session.

type MessageTime

type MessageTime struct {
	Created   json.RawMessage `json:"created"`
	Completed json.RawMessage `json:"completed"`

	Members
}

MessageTime is a message's time.

func (MessageTime) MarshalJSON

func (t MessageTime) MarshalJSON() ([]byte, error)

MarshalJSON writes the times back as they were read.

func (*MessageTime) UnmarshalJSON

func (t *MessageTime) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the times, keeping undeclared members.

type ModelRef

type ModelRef struct {
	ProviderID string `json:"providerID"`
	ModelID    string `json:"modelID"`
	ID         string `json:"id"`
	Variant    string `json:"variant"`

	Members
}

ModelRef is a model reference: a V1 user message's model {providerID, modelID, variant}, or V2's {providerID, id, variant}.

func (ModelRef) MarshalJSON

func (r ModelRef) MarshalJSON() ([]byte, error)

MarshalJSON writes the reference back as it was read.

func (*ModelRef) Name

func (r *ModelRef) Name() string

Name is the model's ID, whichever member holds it.

func (*ModelRef) UnmarshalJSON

func (r *ModelRef) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the reference, keeping undeclared members.

type Part

type Part struct {
	ID        string `json:"id"`
	SessionID string `json:"sessionID"`
	MessageID string `json:"messageID"`
	Type      string `json:"type"`

	// text and reasoning; Metadata is the AI SDK's provider metadata on
	// text and reasoning, a tool part's call-side metadata on a tool.
	Text      string          `json:"text"`
	Synthetic bool            `json:"synthetic"`
	Ignored   bool            `json:"ignored"`
	Time      json.RawMessage `json:"time"`
	Metadata  json.RawMessage `json:"metadata"`

	// file
	Mime     string          `json:"mime"`
	Filename string          `json:"filename"`
	URL      string          `json:"url"`
	Source   json.RawMessage `json:"source"`

	// agent
	Name string `json:"name"`

	// compaction
	Auto        bool   `json:"auto"`
	Overflow    bool   `json:"overflow"`
	TailStartID string `json:"tail_start_id"`

	// subtask
	Prompt      string          `json:"prompt"`
	Description string          `json:"description"`
	Agent       string          `json:"agent"`
	Model       json.RawMessage `json:"model"`
	Command     string          `json:"command"`

	// retry
	Attempt json.RawMessage `json:"attempt"`
	Error   json.RawMessage `json:"error"`

	// step-start, step-finish, snapshot, patch
	Snapshot string          `json:"snapshot"`
	Reason   string          `json:"reason"`
	Cost     json.RawMessage `json:"cost"`
	Tokens   *Tokens         `json:"tokens"`
	Hash     string          `json:"hash"`
	Files    json.RawMessage `json:"files"`

	// tool
	CallID string     `json:"callID"`
	Tool   string     `json:"tool"`
	State  *ToolState `json:"state"`

	Members
}

Part is one part of a V1 message, MessageV2.Part, told apart by Type. A G1 file holds it whole; a G2 row's data holds it without id, sessionID and messageID.

func (Part) MarshalJSON

func (p Part) MarshalJSON() ([]byte, error)

MarshalJSON writes the part back as it was read.

func (*Part) UnmarshalJSON

func (p *Part) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a part, keeping undeclared members and members of another JSON type.

type PartRecord

type PartRecord struct {
	Unit      string
	ID        string
	MessageID string
	Part      *Part
	Raw       json.RawMessage
	Err       error
}

PartRecord is one V1 part as read.

func DecodePart

func DecodePart(unit, id, messageID string, data []byte) *PartRecord

DecodePart reads a V1 part: a G1 file's contents, or a G2 row's data with the row's id and message.

type Project

type Project struct {
	Worktree string
	VCS      string
}

Project is what a project record says of a session's project.

type QueueRow

type QueueRow struct {
	Unit  string
	Table string
	ID    string
	Type  string
	// Seq is admitted_seq or enqueued_seq.
	Seq     int64
	Created int64
	Record  json.RawMessage
}

QueueRow is a row of session_pending or session_inbox: input OpenCode 2 has queued and not yet put in the history.

func DecodeQueueRow

func DecodeQueueRow(table, unit string, cols Columns) *QueueRow

DecodeQueueRow reads a session_pending or session_inbox row.

type Revert

type Revert struct {
	MessageID string
	PartID    string
}

Revert is a staged revert: the message it starts at, and the part within it, when it starts at one.

type Row2

type Row2 struct {
	Unit      string
	ID        string
	SessionID string
	Type      string
	Seq       int64
	Created   int64
	Updated   int64
	Data      *Message2
	// Raw is the row's data as read.
	Raw json.RawMessage
	Err error
}

Row2 is one V2 session_message row as read.

func DecodeRow2

func DecodeRow2(unit string, cols Columns) *Row2

DecodeRow2 reads a session_message row.

type Session

type Session struct {
	Gen Generation
	// Unit names the record in findings: a file's path under the data
	// directory, or <database>:<table>/<id>.
	Unit string

	ID, ProjectID, WorkspaceID, ParentID string
	// ForkSessionID is a V2 fork's origin, and ForkBoundary where it was
	// forked: {type: before|through, messageID}.
	ForkSessionID string
	ForkBoundary  json.RawMessage
	Slug          string
	Directory     string
	Path          string
	Title         string
	// Version is the OpenCode release that created the session.
	Version string
	Agent   string
	Model   *ModelRef
	// Revert is a staged revert, {messageID, partID?, snapshot?, …}.
	Revert json.RawMessage
	// Created and Updated are in milliseconds; HasCreated says the
	// record holds a creation time.
	Created, Updated int64
	HasCreated       bool

	// Record is the session as read: the file's object, or the row's
	// columns as one object.
	Record json.RawMessage
	// Err says why the record could not be read; only Unit and, when
	// the file name or row gave it, ID are then set.
	Err error
}

Session is one copy of a session's record, from any generation: the members a converter reads, and the record itself.

func DecodeSessionFile

func DecodeSessionFile(unit string, data []byte) *Session

DecodeSessionFile reads a G1 session file's contents.

func DecodeSessionRow

func DecodeSessionRow(gen Generation, unit string, cols Columns) *Session

DecodeSessionRow reads a row of the session table (G2) or the session_v2 table (G3).

func (*Session) ForkPoint

func (s *Session) ForkPoint() (Fork, bool)

ForkPoint reads a V2 session's fork boundary.

func (*Session) StagedRevert

func (s *Session) StagedRevert() (Revert, bool)

StagedRevert reads the session's staged revert; false when none is staged.

type SessionError

type SessionError struct {
	Type    string `json:"type"`
	Message string `json:"message"`

	Members
}

SessionError is V2's error: a type, such as provider.rate-limit, permission.rejected or aborted, and a message.

func (SessionError) MarshalJSON

func (e SessionError) MarshalJSON() ([]byte, error)

MarshalJSON writes the error back as it was read.

func (*SessionError) UnmarshalJSON

func (e *SessionError) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the error, keeping undeclared members.

type SessionFile

type SessionFile struct {
	ID          string          `json:"id"`
	Slug        string          `json:"slug"`
	ProjectID   string          `json:"projectID"`
	WorkspaceID string          `json:"workspaceID"`
	Directory   string          `json:"directory"`
	Path        string          `json:"path"`
	ParentID    string          `json:"parentID"`
	Title       string          `json:"title"`
	Version     string          `json:"version"`
	Agent       string          `json:"agent"`
	Model       *ModelRef       `json:"model"`
	Revert      json.RawMessage `json:"revert"`
	Time        *SessionTime    `json:"time"`

	Members
}

SessionFile is a G1 session file, Session.Info: the members a converter reads, the rest kept.

func (SessionFile) MarshalJSON

func (s SessionFile) MarshalJSON() ([]byte, error)

MarshalJSON writes the session back as it was read.

func (*SessionFile) UnmarshalJSON

func (s *SessionFile) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the session, keeping undeclared members and members of another JSON type.

type SessionTime

type SessionTime struct {
	Created json.RawMessage `json:"created"`
	Updated json.RawMessage `json:"updated"`

	Members
}

SessionTime is a G1 session's time.

func (SessionTime) MarshalJSON

func (t SessionTime) MarshalJSON() ([]byte, error)

MarshalJSON writes the times back as they were read.

func (*SessionTime) UnmarshalJSON

func (t *SessionTime) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the times, keeping undeclared members.

type Store

type Store interface {
	// Name names the store in findings: "storage", or the database's
	// file name.
	Name() string
	// Sessions lists every session record the store holds, in any
	// generation, and the records that could not be read as one.
	Sessions() ([]*Session, []*Stray, error)
	// Messages reads a V1 session's messages with their parts, in the
	// order OpenCode reads them, and the records read with them that
	// belong to none of its messages.
	Messages(s *Session) ([]*MessageRecord, []*Stray, error)
	// Rows reads a V2 session's rows in seq order, and its queued
	// input.
	Rows(s *Session) ([]*Row2, []*QueueRow, error)
	// Orphans lists the message, part and row records that name a
	// session not in the set, or a message that does not exist.
	Orphans(sessions map[string]bool) ([]*Stray, error)
	// Project reads a project record.
	Project(id string) (Project, bool)
	// MigrationDone reports whether OpenCode 2 finished copying the V1
	// tables into its own, as its kv table records.
	MigrationDone() bool
}

Store is the records of one OpenCode store: the storage/ tree of a data directory, or a database. Records are read on demand, a session at a time.

type Stray

type Stray struct {
	Unit string
	// Session names the session it was read with, when it was.
	Session string
	// ID is the record's ID, when it has one.
	ID string
	// Kind says what the record is: "session", "message", "part", "row";
	// "directory" or "table" for what holds records and is not one.
	Kind string
	// Why says why it is a stray, and Err the error behind it, when one
	// is.
	Why string
	Err error
	// Malformed says the record could not be read at all.
	Malformed bool
}

Stray is a record read that belongs to no session it can be converted with: a part of no message, a message of no session, a file or row that cannot be read.

type TaskMetadata

type TaskMetadata struct {
	SessionID  string
	Background bool
}

TaskMetadata is what a V1 task tool part's state metadata says of the sub-agent it ran, and V2's subagent tool.

type Time2

type Time2 struct {
	Created   json.RawMessage `json:"created"`
	Streamed  json.RawMessage `json:"streamed"`
	Completed json.RawMessage `json:"completed"`

	Members
}

Time2 is a V2 message's time.

func (Time2) MarshalJSON

func (t Time2) MarshalJSON() ([]byte, error)

MarshalJSON writes the times back as they were read.

func (*Time2) UnmarshalJSON

func (t *Time2) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the times, keeping undeclared members.

type Tokens

type Tokens struct {
	Total     json.RawMessage `json:"total"`
	Input     json.RawMessage `json:"input"`
	Output    json.RawMessage `json:"output"`
	Reasoning json.RawMessage `json:"reasoning"`
	Cache     *Cache          `json:"cache"`

	Members
}

Tokens is a token count: a V1 assistant message's or step-finish part's, or V2's TokenUsage. Input counts neither cache reads nor cache writes.

func (Tokens) MarshalJSON

func (t Tokens) MarshalJSON() ([]byte, error)

MarshalJSON writes the counts back as they were read.

func (*Tokens) UnmarshalJSON

func (t *Tokens) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the counts, keeping undeclared members.

type ToolContent

type ToolContent struct {
	Type string `json:"type"`
	Text string `json:"text"`
	URI  string `json:"uri"`
	Mime string `json:"mime"`
	Name string `json:"name"`
}

ToolContent is one item of a V2 tool's content: text, or a file by URI.

func DecodeToolContent

func DecodeToolContent(raw json.RawMessage) (ToolContent, bool)

DecodeToolContent reads one content item; false when it is not an object.

type ToolState

type ToolState struct {
	Status      string            `json:"status"`
	Input       json.RawMessage   `json:"input"`
	Raw         string            `json:"raw"`
	Output      string            `json:"output"`
	Title       string            `json:"title"`
	Metadata    json.RawMessage   `json:"metadata"`
	Time        *ToolTime         `json:"time"`
	Error       string            `json:"error"`
	Attachments []json.RawMessage `json:"attachments"`

	Members
}

ToolState is a V1 tool part's state, by Status: pending holds input and raw; running input, title, metadata and time; completed input, output, title, metadata, time and attachments; error input, error, metadata and time.

func (*ToolState) Compacted

func (s *ToolState) Compacted() (int64, bool)

Compacted reports whether a completed tool state's output was pruned, and when, in milliseconds.

func (*ToolState) Interrupted

func (s *ToolState) Interrupted() (string, bool)

Interrupted returns the output an errored tool call cleaned up after an abort carries, metadata.output with metadata.interrupted true, which OpenCode sends as the call's output.

func (ToolState) MarshalJSON

func (s ToolState) MarshalJSON() ([]byte, error)

MarshalJSON writes the state back as it was read.

func (*ToolState) Task

func (s *ToolState) Task() TaskMetadata

Task reads a task tool state's metadata: V1 writes sessionId, V2 sessionID.

func (*ToolState) UnmarshalJSON

func (s *ToolState) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the state, keeping undeclared members and members of another JSON type.

type ToolState2

type ToolState2 struct {
	Status   string            `json:"status"`
	Input    json.RawMessage   `json:"input"`
	Content  []json.RawMessage `json:"content"`
	Error    *SessionError     `json:"error"`
	Metadata json.RawMessage   `json:"metadata"`

	Members
}

ToolState2 is a V2 tool's state: streaming holds input as a string, the others as an object; completed holds content, error an error and perhaps content.

func (ToolState2) MarshalJSON

func (s ToolState2) MarshalJSON() ([]byte, error)

MarshalJSON writes the state back as it was read.

func (*ToolState2) Task

func (s *ToolState2) Task() TaskMetadata

Task reads a subagent tool state's metadata: the child session, and whether it runs in the background.

func (*ToolState2) UnmarshalJSON

func (s *ToolState2) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the state, keeping undeclared members and members of another JSON type.

type ToolTime

type ToolTime struct {
	Start     json.RawMessage `json:"start"`
	End       json.RawMessage `json:"end"`
	Compacted json.RawMessage `json:"compacted"`

	Members
}

ToolTime is a tool state's time. Compacted is set when OpenCode pruned the output: every request after it sent a placeholder.

func (ToolTime) MarshalJSON

func (t ToolTime) MarshalJSON() ([]byte, error)

MarshalJSON writes the times back as they were read.

func (*ToolTime) UnmarshalJSON

func (t *ToolTime) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the times, keeping undeclared members.

type Tree

type Tree struct {
	// Root is the data directory.
	Root string
	// Legacy lists the directories of the layout OpenCode wrote before
	// its MessageV2 model, project/<dir>/storage/session, which this
	// package does not read.
	Legacy []string
	// contains filtered or unexported fields
}

Tree is the storage/ tree of a data directory, the G1 store: one JSON file per session, message and part. It is read on demand; a session's messages and parts are read when Tree.Messages is called. A Tree is not safe for concurrent use.

func OpenTree

func OpenTree(root string) (*Tree, error)

OpenTree opens the storage/ tree of the data directory root.

func (*Tree) Messages

func (t *Tree) Messages(s *Session) ([]*MessageRecord, []*Stray, error)

Messages reads a session's message files and each one's part files.

func (*Tree) MigrationDone

func (t *Tree) MigrationDone() bool

MigrationDone: the storage tree is not migrated.

func (*Tree) Name

func (t *Tree) Name() string

Name names the store in findings.

func (*Tree) Orphans

func (t *Tree) Orphans(sessions map[string]bool) ([]*Stray, error)

Orphans lists the message files of sessions not in the set, and the part files of messages no session read named.

func (*Tree) Project

func (t *Tree) Project(id string) (Project, bool)

Project reads storage/project/<id>.json.

func (*Tree) Rows

func (t *Tree) Rows(*Session) ([]*Row2, []*QueueRow, error)

Rows: the storage tree holds no V2 rows.

func (*Tree) Sessions

func (t *Tree) Sessions() ([]*Session, []*Stray, error)

Sessions lists the session files, storage/session/<project>/<id>.json.

Directories

Path Synopsis
Package convert converts OpenCode's sessions into the Agent Session Format: a data directory's storage files, its database's V1 tables and its V2 tables, each session converted once, from the copy that holds the most of what its model saw.
Package convert converts OpenCode's sessions into the Agent Session Format: a data directory's storage files, its database's V1 tables and its V2 tables, each session converted once, from the copy that holds the most of what its model saw.
Package sqlite opens OpenCode's database, opencode.db, and reads its rows as the opencode package's types: the V1 tables session, message and part, and the V2 tables session_v2, session_message, session_pending and session_inbox.
Package sqlite opens OpenCode's database, opencode.db, and reads its rows as the opencode package's types: the V1 tables session, message and part, and the V2 tables session_v2, session_message, session_pending and session_inbox.

Jump to

Keyboard shortcuts

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