opencode

package
v0.5.1 Latest Latest
Warning

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

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

Documentation

Overview

Package opencode implements the Agent interface for OpenCode.

Index

Constants

View Source
const (
	HookNameSessionStart = "session-start"
	HookNameSessionEnd   = "session-end"
	HookNameTurnStart    = "turn-start"
	HookNameTurnEnd      = "turn-end"
	HookNameCompaction   = "compaction"
)

Hook name constants — these become CLI subcommands under `entire hooks opencode`.

Variables

View Source
var FileModificationTools = []string{
	"edit",
	"write",
	"apply_patch",
}

FileModificationTools are tools in OpenCode that modify files on disk. These match the actual tool names from OpenCode's source (packages/opencode/src/tool/):

  • edit: edit.ts — exact string replacement in existing files
  • write: write.ts — create or overwrite files
  • apply_patch: apply_patch.ts — unified diff patches (used by gpt-* models except gpt-4)

Tool selection is mutually exclusive: apply_patch is enabled for gpt-* (non-gpt-4, non-oss) models; edit+write are enabled for all other models (Claude, Gemini, gpt-4, etc.). The batch tool (experimental) creates separate transcript parts per sub-call, so its children are already captured by this list.

Functions

func ExtractAllUserPrompts

func ExtractAllUserPrompts(data []byte) ([]string, error)

ExtractAllUserPrompts extracts all user prompts from raw export JSON transcript bytes. This is a package-level function used by the condensation path.

func ExtractModifiedFiles

func ExtractModifiedFiles(data []byte) ([]string, error)

ExtractModifiedFiles extracts modified file paths from raw export JSON transcript bytes. This is the bytes-based equivalent of ExtractModifiedFilesFromOffset, used by ReadSession.

func ExtractTextFromParts

func ExtractTextFromParts(parts []Part) string

ExtractTextFromParts extracts text content from message parts.

func NewOpenCodeAgent

func NewOpenCodeAgent() agent.Agent

NewOpenCodeAgent creates a new OpenCode agent instance.

func SanitizePathForOpenCode

func SanitizePathForOpenCode(path string) string

SanitizePathForOpenCode converts a path to a safe directory name. Replaces any non-alphanumeric character with a dash (same approach as Claude/Gemini).

func SliceFromMessage

func SliceFromMessage(data []byte, startMessageIndex int) ([]byte, error)

SliceFromMessage returns an OpenCode export transcript scoped to messages starting from startMessageIndex. This is the OpenCode equivalent of transcript.SliceFromLine — for OpenCode's JSON format, scoping is done by message index rather than line offset. Returns the original data if startMessageIndex <= 0. Returns nil, nil if startMessageIndex exceeds the number of messages.

Types

type Cache

type Cache struct {
	Read  int `json:"read"`
	Write int `json:"write"`
}

Cache holds cache-related token counts.

type ExportMessage

type ExportMessage struct {
	Info  MessageInfo `json:"info"`
	Parts []Part      `json:"parts"`
}

ExportMessage represents a single message in the export format. Each message contains info (metadata) and parts (content).

type ExportSession

type ExportSession struct {
	Info     SessionInfo     `json:"info"`
	Messages []ExportMessage `json:"messages"`
}

ExportSession represents the top-level structure of `opencode export` output. This is OpenCode's native format for session data.

func ParseExportSession

func ParseExportSession(data []byte) (*ExportSession, error)

ParseExportSession parses export JSON content into an ExportSession structure.

type MessageInfo

type MessageInfo struct {
	ID        string  `json:"id"`
	SessionID string  `json:"sessionID,omitempty"`
	Role      string  `json:"role"` // "user" or "assistant"
	Time      Time    `json:"time"`
	Tokens    *Tokens `json:"tokens,omitempty"`
	Cost      float64 `json:"cost,omitempty"`
}

MessageInfo contains message metadata.

type OpenCodeAgent

type OpenCodeAgent struct{}

func (*OpenCodeAgent) AreHooksInstalled

func (a *OpenCodeAgent) AreHooksInstalled(ctx context.Context) bool

AreHooksInstalled checks if the Entire plugin file exists and contains the marker.

func (*OpenCodeAgent) CalculateTokenUsage

func (a *OpenCodeAgent) CalculateTokenUsage(transcriptData []byte, fromOffset int) (*agent.TokenUsage, error)

CalculateTokenUsage computes token usage from assistant messages starting at the given offset.

func (*OpenCodeAgent) ChunkTranscript

func (a *OpenCodeAgent) ChunkTranscript(_ context.Context, content []byte, maxSize int) ([][]byte, error)

ChunkTranscript splits an OpenCode export JSON transcript by distributing messages across chunks. OpenCode uses JSON format with {"info": {...}, "messages": [...]} structure.

func (*OpenCodeAgent) Description

func (a *OpenCodeAgent) Description() string

func (*OpenCodeAgent) DetectPresence

func (a *OpenCodeAgent) DetectPresence(ctx context.Context) (bool, error)

func (*OpenCodeAgent) ExtractModifiedFilesFromOffset

func (a *OpenCodeAgent) ExtractModifiedFilesFromOffset(path string, startOffset int) ([]string, int, error)

ExtractModifiedFilesFromOffset extracts files modified by tool calls from the given message offset.

func (*OpenCodeAgent) FormatResumeCommand

func (a *OpenCodeAgent) FormatResumeCommand(sessionID string) string

func (*OpenCodeAgent) GetSessionDir

func (a *OpenCodeAgent) GetSessionDir(repoPath string) (string, error)

GetSessionDir returns the directory where Entire stores OpenCode session transcripts. Transcripts are ephemeral handoff files between the TS plugin and the Go hook handler. Once checkpointed, the data lives on git refs and the file is disposable. Stored in os.TempDir()/entire-opencode/<sanitized-path>/ to avoid squatting on OpenCode's own directories (~/.opencode/ is project-level, not home-level).

func (*OpenCodeAgent) GetSessionID

func (a *OpenCodeAgent) GetSessionID(input *agent.HookInput) string

func (*OpenCodeAgent) GetSupportedHooks

func (a *OpenCodeAgent) GetSupportedHooks() []agent.HookType

GetSupportedHooks returns the normalized lifecycle events this agent supports. OpenCode's native hooks map to standard agent lifecycle events:

  • session-start → HookSessionStart
  • session-end → HookSessionEnd
  • turn-start → HookUserPromptSubmit (user prompt triggers a turn)
  • turn-end → HookStop (agent response complete)

Note: HookNames() returns 5 hooks (including "compaction"), but GetSupportedHooks() returns only 4. The "compaction" hook is OpenCode-specific with no standard HookType mapping — it is handled via ParseHookEvent but not advertised as a standard lifecycle event.

func (*OpenCodeAgent) GetTranscriptPosition

func (a *OpenCodeAgent) GetTranscriptPosition(path string) (int, error)

GetTranscriptPosition returns the number of messages in the transcript.

func (*OpenCodeAgent) HookNames

func (a *OpenCodeAgent) HookNames() []string

HookNames returns the hook verbs this agent supports.

func (*OpenCodeAgent) InstallHooks

func (a *OpenCodeAgent) InstallHooks(ctx context.Context, localDev bool, force bool) (int, error)

InstallHooks writes the Entire plugin file to .opencode/plugins/entire.ts. Returns 1 if the plugin was installed, 0 if already present (idempotent).

func (*OpenCodeAgent) IsPreview

func (a *OpenCodeAgent) IsPreview() bool

func (*OpenCodeAgent) Name

func (a *OpenCodeAgent) Name() types.AgentName

func (*OpenCodeAgent) ParseHookEvent

func (a *OpenCodeAgent) ParseHookEvent(ctx context.Context, hookName string, stdin io.Reader) (*agent.Event, error)

ParseHookEvent translates OpenCode hook calls into normalized lifecycle events.

func (*OpenCodeAgent) PrepareTranscript

func (a *OpenCodeAgent) PrepareTranscript(ctx context.Context, sessionRef string) error

PrepareTranscript ensures the OpenCode transcript file is up-to-date by calling `opencode export`. OpenCode's transcript is created/updated via `opencode export`, but condensation may need fresh data mid-turn (e.g., during mid-turn commits or resumed sessions where the cached file is stale). This method always refreshes the transcript to ensure the latest agent activity is captured.

func (*OpenCodeAgent) ProtectedDirs

func (a *OpenCodeAgent) ProtectedDirs() []string

func (*OpenCodeAgent) ReadSession

func (a *OpenCodeAgent) ReadSession(input *agent.HookInput) (*agent.AgentSession, error)

func (*OpenCodeAgent) ReadTranscript

func (a *OpenCodeAgent) ReadTranscript(sessionRef string) ([]byte, error)

ReadTranscript reads the transcript for a session. The sessionRef is expected to be a path to the export JSON file.

func (*OpenCodeAgent) ReassembleTranscript

func (a *OpenCodeAgent) ReassembleTranscript(chunks [][]byte) ([]byte, error)

ReassembleTranscript merges OpenCode export JSON chunks by combining their message arrays.

func (*OpenCodeAgent) ResolveSessionFile

func (a *OpenCodeAgent) ResolveSessionFile(sessionDir, agentSessionID string) string

func (*OpenCodeAgent) Type

func (a *OpenCodeAgent) Type() types.AgentType

func (*OpenCodeAgent) UninstallHooks

func (a *OpenCodeAgent) UninstallHooks(ctx context.Context) error

UninstallHooks removes the Entire plugin file.

func (*OpenCodeAgent) WriteSession

func (a *OpenCodeAgent) WriteSession(ctx context.Context, session *agent.AgentSession) error

type Part

type Part struct {
	ID     string     `json:"id,omitempty"` // Part ID (e.g., "prt_..."), added in OpenCode 1.2.x
	Type   string     `json:"type"`         // "text", "tool", etc.
	Text   string     `json:"text,omitempty"`
	Tool   string     `json:"tool,omitempty"`
	CallID string     `json:"callID,omitempty"`
	State  *ToolState `json:"state,omitempty"`
}

Part represents a message part (text, tool, etc.).

type SessionInfo

type SessionInfo struct {
	ID        string `json:"id"`
	Title     string `json:"title,omitempty"`
	CreatedAt int64  `json:"createdAt,omitempty"`
	UpdatedAt int64  `json:"updatedAt,omitempty"`
}

SessionInfo contains session metadata from the export.

type Time

type Time struct {
	Created   int64 `json:"created"`
	Completed int64 `json:"completed,omitempty"`
}

Time holds message timestamps.

type Tokens

type Tokens struct {
	Input     int   `json:"input"`
	Output    int   `json:"output"`
	Reasoning int   `json:"reasoning"`
	Cache     Cache `json:"cache"`
}

Tokens holds token usage from assistant messages.

type ToolFileInfo added in v0.4.8

type ToolFileInfo struct {
	FilePath     string `json:"filePath"`
	RelativePath string `json:"relativePath,omitempty"`
}

ToolFileInfo represents a file affected by a tool operation.

type ToolState

type ToolState struct {
	Status   string             `json:"status"` // "pending", "running", "completed", "error"
	Input    map[string]any     `json:"input,omitempty"`
	Output   string             `json:"output,omitempty"`
	Metadata *ToolStateMetadata `json:"metadata,omitempty"`
}

ToolState represents tool execution state.

type ToolStateMetadata added in v0.4.8

type ToolStateMetadata struct {
	Files []ToolFileInfo `json:"files,omitempty"`
}

ToolStateMetadata holds metadata from tool execution results.

Jump to

Keyboard shortcuts

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