opencodeacp

package module
v0.0.0-...-e90b60d Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: GPL-3.0 Imports: 39 Imported by: 0

README

acp-go-opencode

acp-go-opencode is a Go ACP agent for OpenCode. It speaks ACP on the provided stdin/stdout streams and runs one isolated opencode serve process for each ACP session.

OpenCode owns model execution and native state. This package owns ACP dispatch, process launch, per-session XDG isolation, REST/SSE event mapping, permission requests, config options, and opencode-state-v1 session storage.

Install

go install github.com/savid/acp-go-opencode/cmd/acp-go-opencode@latest

Local run:

go run ./cmd/acp-go-opencode -path "$(command -v opencode)"

The command reserves stdout for ACP JSON-RPC. Diagnostics go to stderr.

Embedded Go

err := opencodeacp.Serve(ctx, input, output,
	opencodeacp.WithExecutablePath("opencode"),
	opencodeacp.WithHome("/tmp/opencode-acp-home"),
	opencodeacp.WithDefaultModel("opencode/big-pickle"),
)

Public Surface

The package exports NewAgent, Serve, common process options, OpenCode options, request builders, ForkSessionMethod, RawEventMethod, and the SessionStore API. Session durability uses:

const SessionStoreFormat = "opencode-state-v1"

Forking is available only through _opencode/session/fork.

Examples

go run ./examples/minimal-client "Reply with hello from ACP"
go run ./examples/interactive-chat
go run ./examples/resume-from-file

Development

make test
make test-integration-smoke
make audit

Live prompt, permission, and elicitation checks are guarded by ACP_GO_OPENCODE_RUN_LIVE_TOKENS=1.

Documentation

Overview

Package opencodeacp exposes OpenCode as an Agent Client Protocol agent.

The package runs one authenticated loopback `opencode serve` process per ACP session and maps native REST/SSE state to ACP methods and notifications.

Index

Constants

View Source
const (
	ForkSessionMethod = "_opencode/session/fork"
	RawEventMethod    = "_opencode/rawEvent"
)
View Source
const (
	SessionStoreMainSubpath = ""
	SessionStoreFormat      = "opencode-state-v1"
)

Variables

This section is empty.

Functions

func DeleteSessionRequest

func DeleteSessionRequest(sessionID acp.SessionId) acp.UnstableDeleteSessionRequest

func ForkSessionRequest

func ForkSessionRequest(sessionID acp.SessionId, cwd string, opts ...SessionRequestOption) acp.UnstableForkSessionRequest

func HTTPMCPServer

func HTTPMCPServer(name string, url string, headers map[string]string) acp.McpServer

func LoadSessionRequest

func LoadSessionRequest(sessionID acp.SessionId, cwd string, opts ...SessionRequestOption) acp.LoadSessionRequest

func NewSessionRequest

func NewSessionRequest(cwd string, opts ...SessionRequestOption) acp.NewSessionRequest

func PromptRequest

func PromptRequest(sessionID acp.SessionId, blocks ...acp.ContentBlock) acp.PromptRequest

func ResumeSessionRequest

func ResumeSessionRequest(sessionID acp.SessionId, cwd string, opts ...SessionRequestOption) acp.ResumeSessionRequest

func Serve

func Serve(ctx context.Context, input io.Reader, output io.Writer, opts ...Option) error

func SetModelRequest

func SetModelRequest(sessionID acp.SessionId, model string) acp.SetSessionConfigOptionRequest

func StdioMCPServer

func StdioMCPServer(name string, command string, args []string, env map[string]string) acp.McpServer

func TextPromptRequest

func TextPromptRequest(sessionID acp.SessionId, text string) acp.PromptRequest

Types

type Agent

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

Agent exposes OpenCode through ACP.

func NewAgent

func NewAgent(opts ...Option) *Agent

func (*Agent) Authenticate

func (a *Agent) Authenticate(_ context.Context, params acp.AuthenticateRequest) (acp.AuthenticateResponse, error)

func (*Agent) Cancel

func (a *Agent) Cancel(ctx context.Context, params acp.CancelNotification) error

func (*Agent) Close

func (a *Agent) Close() error

func (*Agent) CloseSession

func (a *Agent) CloseSession(ctx context.Context, params acp.CloseSessionRequest) (acp.CloseSessionResponse, error)

func (*Agent) HandleExtensionMethod

func (a *Agent) HandleExtensionMethod(ctx context.Context, method string, params json.RawMessage) (any, error)

func (*Agent) Initialize

func (a *Agent) Initialize(_ context.Context, params acp.InitializeRequest) (acp.InitializeResponse, error)

func (*Agent) ListSessions

func (a *Agent) ListSessions(ctx context.Context, params acp.ListSessionsRequest) (acp.ListSessionsResponse, error)

func (*Agent) LoadSession

func (a *Agent) LoadSession(ctx context.Context, params acp.LoadSessionRequest) (acp.LoadSessionResponse, error)

func (*Agent) Logout

func (*Agent) NewSession

func (a *Agent) NewSession(ctx context.Context, params acp.NewSessionRequest) (acp.NewSessionResponse, error)

func (*Agent) Prompt

func (a *Agent) Prompt(ctx context.Context, params acp.PromptRequest) (acp.PromptResponse, error)

func (*Agent) ResumeSession

func (a *Agent) ResumeSession(ctx context.Context, params acp.ResumeSessionRequest) (acp.ResumeSessionResponse, error)

type ConcurrencyLimits

type ConcurrencyLimits struct {
	MaxActiveSessions        int
	MaxConcurrentPrompts     int
	MaxConcurrentClientCalls int
}

ConcurrencyLimits bounds work accepted by one Agent.

type InMemorySessionStore

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

func NewInMemorySessionStore

func NewInMemorySessionStore() *InMemorySessionStore

func (*InMemorySessionStore) Append

func (s *InMemorySessionStore) Append(ctx context.Context, key SessionKey, entries []SessionStoreEntry) error

func (*InMemorySessionStore) Delete

func (s *InMemorySessionStore) Delete(ctx context.Context, key SessionKey) error

func (*InMemorySessionStore) ListSessions

func (s *InMemorySessionStore) ListSessions(ctx context.Context) ([]SessionSummary, error)

func (*InMemorySessionStore) ListSubkeys

func (s *InMemorySessionStore) ListSubkeys(ctx context.Context, key SessionKey) ([]string, error)

func (*InMemorySessionStore) Load

func (*InMemorySessionStore) Replace

func (s *InMemorySessionStore) Replace(ctx context.Context, main SessionKey, replacements []SessionStoreReplacement) error

type ListSessionsRequestOption

type ListSessionsRequestOption func(*acp.ListSessionsRequest)

func WithListSessionsCursor

func WithListSessionsCursor(cursor string) ListSessionsRequestOption

func WithListSessionsCwd

func WithListSessionsCwd(cwd string) ListSessionsRequestOption

func WithListSessionsMeta

func WithListSessionsMeta(meta map[string]any) ListSessionsRequestOption

type OpenCodeOption

type OpenCodeOption func(*OpenCodeOptions)

func WithOpenCodeEnv

func WithOpenCodeEnv(env map[string]string) OpenCodeOption

func WithOpenCodeMode

func WithOpenCodeMode(mode string) OpenCodeOption

func WithOpenCodeModel

func WithOpenCodeModel(model string) OpenCodeOption

func WithOpenCodeOutputSchema

func WithOpenCodeOutputSchema(schema map[string]any) OpenCodeOption

func WithOpenCodePermission

func WithOpenCodePermission(permission string) OpenCodeOption

type OpenCodeOptions

type OpenCodeOptions struct {
	Model        string            `json:"model,omitempty"`
	Env          map[string]string `json:"env,omitempty"`
	OutputSchema map[string]any    `json:"outputSchema,omitempty"`
	Mode         string            `json:"mode,omitempty"`
	Permission   string            `json:"permission,omitempty"`
}

OpenCodeOptions is the stable OpenCode-specific subset accepted at _meta.opencode.options.

func NewOpenCodeOptions

func NewOpenCodeOptions(opts ...OpenCodeOption) OpenCodeOptions

func (OpenCodeOptions) Meta

func (options OpenCodeOptions) Meta() map[string]any

Meta returns an ACP _meta object for the supported OpenCode-specific options.

type Option

type Option func(*Options)

Option configures the OpenCode ACP agent.

func WithAgentName

func WithAgentName(name string) Option

func WithAgentTitle

func WithAgentTitle(title string) Option

func WithAgentVersion

func WithAgentVersion(version string) Option

func WithConcurrencyLimits

func WithConcurrencyLimits(limits ConcurrencyLimits) Option

func WithDefaultModel

func WithDefaultModel(model string) Option

func WithEnv

func WithEnv(env map[string]string) Option

func WithExecutablePath

func WithExecutablePath(path string) Option

func WithHome

func WithHome(path string) Option

WithHome sets the parent root under which isolated per-session OpenCode XDG data, config, cache, and state directories are created.

func WithLogger

func WithLogger(logger *slog.Logger) Option

func WithMeterProvider

func WithMeterProvider(provider metric.MeterProvider) Option

func WithOpenCodeHealthCheckTimeout

func WithOpenCodeHealthCheckTimeout(timeout time.Duration) Option

func WithOpenCodeLogLevel

func WithOpenCodeLogLevel(level string) Option

func WithOpenCodeMinimumVersion

func WithOpenCodeMinimumVersion(version string) Option

func WithOpenCodePure

func WithOpenCodePure(enabled bool) Option

func WithOpenCodeQuestionTool

func WithOpenCodeQuestionTool(enabled bool) Option

func WithSessionStore

func WithSessionStore(store SessionStore) Option

func WithSessionStoreLoadTimeout

func WithSessionStoreLoadTimeout(timeout time.Duration) Option

func WithTextMapPropagator

func WithTextMapPropagator(propagator propagation.TextMapPropagator) Option

func WithTracerProvider

func WithTracerProvider(provider trace.TracerProvider) Option

type Options

type Options struct {
	AgentName    string
	AgentTitle   string
	AgentVersion string

	ExecutablePath string
	Home           string
	DefaultModel   string
	Env            map[string]string

	Logger            *slog.Logger
	TracerProvider    trace.TracerProvider
	MeterProvider     metric.MeterProvider
	TextMapPropagator propagation.TextMapPropagator

	SessionStore            SessionStore
	SessionStoreLoadTimeout time.Duration
	ConcurrencyLimits       ConcurrencyLimits

	Pure               bool
	QuestionTool       bool
	LogLevel           string
	MinimumVersion     string
	HealthCheckTimeout time.Duration
	// contains filtered or unexported fields
}

Options configures the ACP agent process and OpenCode sessions it starts.

type SessionKey

type SessionKey struct {
	SessionID string
	Subpath   string
}

type SessionRequestOption

type SessionRequestOption func(*sessionRequestConfig)

func WithSessionAdditionalDirectories

func WithSessionAdditionalDirectories(paths ...string) SessionRequestOption

func WithSessionMCPServers

func WithSessionMCPServers(servers ...acp.McpServer) SessionRequestOption

func WithSessionMeta

func WithSessionMeta(meta map[string]any) SessionRequestOption

func WithSessionOpenCodeOptions

func WithSessionOpenCodeOptions(options OpenCodeOptions) SessionRequestOption

func WithSessionOutputSchema

func WithSessionOutputSchema(schema map[string]any) SessionRequestOption

func WithSessionRawEvents

func WithSessionRawEvents(enabled bool) SessionRequestOption

type SessionStore

type SessionStore interface {
	Append(ctx context.Context, key SessionKey, entries []SessionStoreEntry) error
	Load(ctx context.Context, key SessionKey) ([]SessionStoreEntry, error)
	Replace(ctx context.Context, main SessionKey, replacements []SessionStoreReplacement) error
	Delete(ctx context.Context, key SessionKey) error
	ListSessions(ctx context.Context) ([]SessionSummary, error)
	ListSubkeys(ctx context.Context, key SessionKey) ([]string, error)
}

type SessionStoreEntry

type SessionStoreEntry = json.RawMessage

type SessionStoreReplacement

type SessionStoreReplacement struct {
	Key     SessionKey
	Entries []SessionStoreEntry
}

type SessionSummary

type SessionSummary struct {
	SessionID          string
	UpdatedAtUnixMilli int64
	Cwd                string
	Title              string
	Meta               map[string]any
}

Directories

Path Synopsis
cmd
acp-go-opencode command
examples
minimal-client command
internal

Jump to

Keyboard shortcuts

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