adapters

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoAdapterDetected is returned when no adapter can handle the current environment
	ErrNoAdapterDetected = errors.New("no adapter detected for current environment")

	// ErrAdapterNotFound is returned when a specific adapter is not registered
	ErrAdapterNotFound = errors.New("adapter not found")

	// ErrSessionNotFound is returned when a session file cannot be located
	ErrSessionNotFound = errors.New("session file not found")

	// ErrWatchNotSupported is returned when an adapter does not support real-time watching
	ErrWatchNotSupported = errors.New("watch not supported for this adapter")
)

Functions

func ListAdapters

func ListAdapters() []string

ListAdapters returns the names of all registered adapters

func Register

func Register(adapter Adapter)

Register adds an adapter to the registry Panics if an adapter with the same name is already registered

func ResetRegistry

func ResetRegistry()

ResetRegistry clears all registered adapters (for testing only)

Types

type Adapter

type Adapter interface {
	// Name returns the adapter name (e.g., "claude-code")
	Name() string

	// Detect checks if this adapter can handle the current environment
	// Returns true if the agent's session files are present and readable
	Detect() bool

	// FindSessionFile locates the session file for correlation
	// Called after ox agent prime to find the matching agent session
	// agentID is the unique identifier written during prime
	// since filters to sessions created after this time
	FindSessionFile(agentID string, since time.Time) (string, error)

	// Read reads all entries from a session file
	// Returns entries in chronological order
	Read(sessionPath string) ([]RawEntry, error)

	// ReadMetadata extracts session metadata (agent version, model) from a session file.
	// Returns nil if metadata cannot be determined.
	ReadMetadata(sessionPath string) (*SessionMetadata, error)

	// Watch monitors a session file for new entries (for real-time capture)
	// The returned channel receives entries as they appear
	// The channel is closed when ctx is canceled or an error occurs
	Watch(ctx context.Context, sessionPath string) (<-chan RawEntry, error)
}

Adapter reads conversation data from a coding agent's session files

func DetectAdapter

func DetectAdapter() (Adapter, error)

DetectAdapter finds the appropriate adapter for the current environment Iterates through all registered adapters and returns the first one that detects Returns ErrNoAdapterDetected if no adapter can handle the environment

func GetAdapter

func GetAdapter(name string) (Adapter, error)

GetAdapter returns a specific adapter by name. Accepts canonical names ("claude-code"), display names ("Claude Code"), and shorthand ("claude"). Case-insensitive for aliases. Returns ErrAdapterNotFound if no adapter with that name is registered.

type ClaudeCodeAdapter

type ClaudeCodeAdapter struct{}

ClaudeCodeAdapter reads Claude Code session files stored as JSONL in ~/.claude/projects/<project-hash>/*.jsonl

func (*ClaudeCodeAdapter) Detect

func (a *ClaudeCodeAdapter) Detect() bool

Detect checks if Claude Code session files are present

func (*ClaudeCodeAdapter) FindSessionFile

func (a *ClaudeCodeAdapter) FindSessionFile(agentID string, since time.Time) (string, error)

FindSessionFile locates the most recent session file matching criteria. It searches through all project directories for JSONL files modified after 'since', then scans for content matching the agentID (from ox agent prime output).

func (*ClaudeCodeAdapter) Name

func (a *ClaudeCodeAdapter) Name() string

Name returns the adapter identifier

func (*ClaudeCodeAdapter) Read

func (a *ClaudeCodeAdapter) Read(sessionPath string) ([]RawEntry, error)

Read parses all entries from a Claude Code JSONL session file

func (*ClaudeCodeAdapter) ReadMetadata

func (a *ClaudeCodeAdapter) ReadMetadata(sessionPath string) (*SessionMetadata, error)

ReadMetadata extracts session metadata (agent version, model) from a Claude Code session. It scans the session file for version and model information from the JSONL entries.

func (*ClaudeCodeAdapter) Watch

func (a *ClaudeCodeAdapter) Watch(ctx context.Context, sessionPath string) (<-chan RawEntry, error)

Watch monitors a session file for new entries using fsnotify. It uses debouncing to avoid reading partial writes when multiple file system events fire rapidly during a single write operation.

type CodexAdapter added in v0.3.0

type CodexAdapter struct{}

CodexAdapter reads OpenAI Codex CLI session files stored as JSONL in ~/.codex/sessions/YYYY/MM/DD/rollout-TIMESTAMP-UUID.jsonl

Codex session entry types:

  • session_meta: session start metadata (cwd, cli_version, session id)
  • turn_context: per-turn config including model
  • response_item: conversation data (messages, function calls)
  • event_msg: infrastructure events (task_started, token counts) — skipped

response_item subtypes:

  • type=message, role=user: user prompt (content[].input_text.text)
  • type=message, role=assistant: AI response (content[].output_text.text)
  • type=message, role=developer: system instructions — skipped
  • type=function_call: tool invocation (name, arguments)
  • type=function_call_output: tool result — skipped (captured via function_call)
  • type=reasoning: encrypted model reasoning — skipped

Plans are embedded in the session as assistant messages, not separate files.

func (*CodexAdapter) Detect added in v0.3.0

func (a *CodexAdapter) Detect() bool

Detect checks if Codex session files are present

func (*CodexAdapter) FindSessionFile added in v0.3.0

func (a *CodexAdapter) FindSessionFile(agentID string, since time.Time) (string, error)

FindSessionFile locates the Codex session file for the current project. It searches recent date directories under ~/.codex/sessions/YYYY/MM/DD/, matches by cwd and optionally agentID (from ox agent prime output).

func (*CodexAdapter) Name added in v0.3.0

func (a *CodexAdapter) Name() string

Name returns the adapter identifier

func (*CodexAdapter) Read added in v0.3.0

func (a *CodexAdapter) Read(sessionPath string) ([]RawEntry, error)

Read parses all conversation entries from a Codex JSONL session file. Plans are embedded as assistant messages — no separate plan file exists.

func (*CodexAdapter) ReadMetadata added in v0.3.0

func (a *CodexAdapter) ReadMetadata(sessionPath string) (*SessionMetadata, error)

ReadMetadata extracts session metadata (CLI version and model) from a Codex session. CLI version comes from session_meta, model from the first turn_context.

func (*CodexAdapter) Watch added in v0.3.0

func (a *CodexAdapter) Watch(ctx context.Context, sessionPath string) (<-chan RawEntry, error)

Watch monitors a Codex session file for new entries using fsnotify with debouncing.

type GenericJSONLAdapter added in v0.3.0

type GenericJSONLAdapter struct{}

GenericJSONLAdapter reads SageOx-compatible JSONL from a file that any coding agent writes to. Unlike the Claude Code adapter which reads agent-native files, this adapter reads a standardized format that agents write to via `ox agent session log` or direct JSONL writes.

func (*GenericJSONLAdapter) Detect added in v0.3.0

func (a *GenericJSONLAdapter) Detect() bool

Detect always returns false. The generic adapter is never auto-detected -- it is used via explicit GetAdapter() or alias resolution. Deep adapters (e.g. Claude Code) take priority via DetectAdapter().

func (*GenericJSONLAdapter) FindSessionFile added in v0.3.0

func (a *GenericJSONLAdapter) FindSessionFile(_ string, _ time.Time) (string, error)

FindSessionFile is not supported by the generic adapter. The session file path is created by session start and passed through recording state.

func (*GenericJSONLAdapter) Name added in v0.3.0

func (a *GenericJSONLAdapter) Name() string

Name returns the adapter identifier.

func (*GenericJSONLAdapter) Read added in v0.3.0

func (a *GenericJSONLAdapter) Read(sessionPath string) ([]RawEntry, error)

Read parses all entries from a SageOx-compatible JSONL session file. It streams line-by-line, skipping header/footer lines and malformed JSON. Empty files return an empty slice (not an error).

func (*GenericJSONLAdapter) ReadMetadata added in v0.3.0

func (a *GenericJSONLAdapter) ReadMetadata(sessionPath string) (*SessionMetadata, error)

ReadMetadata extracts session metadata from the first line of a JSONL file. If the first line is a header with a metadata object, agent_version and model are extracted. Returns nil if no header or the fields are missing.

func (*GenericJSONLAdapter) Watch added in v0.3.0

func (a *GenericJSONLAdapter) Watch(_ context.Context, _ string) (<-chan RawEntry, error)

Watch is not supported by the generic adapter. Session data is read at stop time via Read(), not streamed in real time.

type RawEntry

type RawEntry struct {
	// Timestamp when this entry was created
	Timestamp time.Time

	// Role identifies the speaker: "user", "assistant", "system", "tool"
	Role string

	// Content is the message text or tool output
	Content string

	// ToolName is the name of the tool invoked (only for role="tool")
	ToolName string

	// ToolInput is the input provided to the tool (only for role="tool")
	ToolInput string

	// Raw contains the original data for debugging and auditing
	Raw json.RawMessage
}

RawEntry represents a conversation turn from any agent

type SessionMetadata

type SessionMetadata struct {
	// AgentVersion is the version of the coding agent (e.g., "1.0.3" for Claude Code)
	AgentVersion string

	// Model is the LLM model used (e.g., "claude-sonnet-4-20250514")
	Model string
}

SessionMetadata contains metadata extracted from agent session files. This captures which agent and model were used for the session.

Jump to

Keyboard shortcuts

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