Documentation
¶
Overview ¶
Package bus provides a typed event bus for inter-component communication. Based on opencode's bus system.
Index ¶
- Constants
- func WithBus(ctx context.Context, b *Bus) context.Context
- func WithPermissionManager(ctx context.Context, pm *PermissionManager) context.Context
- func WithQuestionManager(ctx context.Context, qm *QuestionManager) context.Context
- type AskInput
- type Bus
- type ErrPermissionNeeded
- type ErrQuestionNeeded
- type Event
- type PermissionAskedPayload
- type PermissionDeniedError
- type PermissionManager
- type PermissionRepliedPayload
- type PermissionRequest
- type PermissionRule
- type QuestionAskedPayload
- type QuestionInfo
- type QuestionManager
- type QuestionOption
- type QuestionRejectedPayload
- type QuestionRepliedPayload
- type SessionCompactedPayload
- type SessionUpdatedPayload
- type Subscription
- type ToolContext
Constants ¶
const ( // Question events QuestionAsked = "question.asked" QuestionReplied = "question.replied" QuestionRejected = "question.rejected" // Permission events PermissionAsked = "permission.asked" PermissionReplied = "permission.replied" PermissionRejected = "permission.rejected" // Session events SessionCreated = "session.created" SessionUpdated = "session.updated" SessionCompacted = "session.compacted" // Aliases for code clarity EventSessionUpdated = SessionUpdated EventSessionCompacted = SessionCompacted // Message events MessageCreated = "message.created" MessageUpdated = "message.updated" // Tool events ToolStarted = "tool.started" ToolCompleted = "tool.completed" // Stream events (published by runner during LLM streaming) StreamTextDelta = "stream.text_delta" StreamToolCall = "stream.tool_call" StreamToolResult = "stream.tool_result" StreamStepComplete = "stream.step_complete" )
Event type constants - matches opencode's event types.
Variables ¶
This section is empty.
Functions ¶
func WithPermissionManager ¶
func WithPermissionManager(ctx context.Context, pm *PermissionManager) context.Context
WithPermissionManager returns a context with the given PermissionManager.
func WithQuestionManager ¶
func WithQuestionManager(ctx context.Context, qm *QuestionManager) context.Context
WithQuestionManager returns a context with the given QuestionManager.
Types ¶
type AskInput ¶
type AskInput struct {
SessionID string
Questions []QuestionInfo
Tool *ToolContext
}
AskInput is the input for asking questions.
type Bus ¶
type Bus struct {
// contains filtered or unexported fields
}
Bus is the main event bus for publishing and subscribing to events.
func BusFromContext ¶
BusFromContext extracts a Bus from context. Panics if not set — the runner must inject it via WithBus.
func (*Bus) Once ¶
Once subscribes to an event and automatically unsubscribes after the callback returns true.
func (*Bus) Publish ¶
Publish sends an event to all subscribers of that event type and wildcard subscribers.
func (*Bus) Subscribe ¶
func (b *Bus) Subscribe(eventType string, callback Subscription) func()
Subscribe registers a callback for a specific event type. Returns an unsubscribe function.
func (*Bus) SubscribeAll ¶
func (b *Bus) SubscribeAll(callback Subscription) func()
SubscribeAll registers a callback for all events (wildcard).
type ErrPermissionNeeded ¶
type ErrPermissionNeeded struct {
Permission string `json:"permission"`
Patterns []string `json:"patterns"`
ToolCallID string `json:"toolCallID"`
Metadata map[string]any `json:"metadata,omitempty"`
}
ErrPermissionNeeded is returned when no permission rule matches. Implements FatalToolError so the executor propagates it up.
func (*ErrPermissionNeeded) Error ¶
func (e *ErrPermissionNeeded) Error() string
func (*ErrPermissionNeeded) FatalToolError ¶
func (e *ErrPermissionNeeded) FatalToolError() bool
type ErrQuestionNeeded ¶
type ErrQuestionNeeded struct {
Questions []QuestionInfo `json:"questions"`
ToolCallID string `json:"toolCallID"`
}
ErrQuestionNeeded is returned when no pre-loaded answer is available.
func (*ErrQuestionNeeded) Error ¶
func (e *ErrQuestionNeeded) Error() string
func (*ErrQuestionNeeded) FatalToolError ¶
func (e *ErrQuestionNeeded) FatalToolError() bool
type PermissionAskedPayload ¶
type PermissionAskedPayload struct {
ID string `json:"id"`
SessionID string `json:"sessionID"`
Permission string `json:"permission"`
Patterns []string `json:"patterns"`
Always []string `json:"always,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
ToolCallID string `json:"toolCallId,omitempty"`
}
PermissionAskedPayload is the payload for permission.asked events.
type PermissionDeniedError ¶
PermissionDeniedError is returned when permission is denied by a rule.
func (*PermissionDeniedError) Error ¶
func (e *PermissionDeniedError) Error() string
type PermissionManager ¶
type PermissionManager struct {
// contains filtered or unexported fields
}
PermissionManager handles permission evaluation via rules. Non-blocking: Ask() returns immediately with either nil (allowed), PermissionDeniedError (denied by rule), or ErrPermissionNeeded (no rule matches).
func NewPermissionManager ¶
func NewPermissionManager(b *Bus) *PermissionManager
NewPermissionManager creates a new permission manager. The bus parameter is required — there is no global bus.
func PermissionManagerFromContext ¶
func PermissionManagerFromContext(ctx context.Context) *PermissionManager
PermissionManagerFromContext extracts a PermissionManager from context. Panics if not set — the runner must inject it via WithPermissionManager.
func (*PermissionManager) AddRule ¶
func (pm *PermissionManager) AddRule(rule PermissionRule)
AddRule adds a permission rule.
func (*PermissionManager) Ask ¶
func (pm *PermissionManager) Ask(ctx context.Context, req PermissionRequest) error
Ask evaluates permission rules and returns immediately. Returns nil if all patterns are allowed, PermissionDeniedError if denied, or ErrPermissionNeeded if no rule matches (caller should suspend).
func (*PermissionManager) SetRules ¶
func (pm *PermissionManager) SetRules(rules []PermissionRule)
SetRules sets the permission rules.
type PermissionRepliedPayload ¶
type PermissionRepliedPayload struct {
SessionID string `json:"sessionID"`
RequestID string `json:"requestID"`
Response string `json:"response"` // "once", "always", "reject"
}
PermissionRepliedPayload is the payload for permission.replied events.
type PermissionRequest ¶
type PermissionRequest struct {
ID string
SessionID string
Permission string // Permission type (e.g., "edit", "bash", "read")
Patterns []string // Patterns being accessed (e.g., file paths)
Always []string // Patterns to approve for "always" response
Metadata map[string]any // Additional metadata (e.g., diff for edits)
ToolCallID string // The tool call ID
}
PermissionRequest represents a permission request.
type PermissionRule ¶
type PermissionRule struct {
Permission string `json:"permission"` // Permission type to match (supports wildcards)
Pattern string `json:"pattern"` // Pattern to match (supports wildcards)
Action string `json:"action"` // "allow", "deny", or "ask"
}
PermissionRule defines an auto-approve or auto-deny rule.
type QuestionAskedPayload ¶
type QuestionAskedPayload struct {
ID string `json:"id"`
SessionID string `json:"sessionID"`
Questions []QuestionInfo `json:"questions"`
Tool *ToolContext `json:"tool,omitempty"`
}
QuestionAskedPayload is the payload for question.asked events.
type QuestionInfo ¶
type QuestionInfo struct {
Question string `json:"question"`
Header string `json:"header"`
Options []QuestionOption `json:"options"`
Multiple bool `json:"multiple,omitempty"`
Custom bool `json:"custom,omitempty"`
}
QuestionInfo represents a single question.
type QuestionManager ¶
type QuestionManager struct {
// contains filtered or unexported fields
}
QuestionManager handles question ask/reply lifecycle. Non-blocking: Ask() checks pre-loaded answers or auto-answer mode, returning ErrQuestionNeeded if no answer is available.
func NewQuestionManager ¶
func NewQuestionManager(b *Bus) *QuestionManager
NewQuestionManager creates a new question manager. The bus parameter is required — there is no global bus.
func QuestionManagerFromContext ¶
func QuestionManagerFromContext(ctx context.Context) *QuestionManager
QuestionManagerFromContext extracts a QuestionManager from context. Panics if not set — the runner must inject it via WithQuestionManager.
func (*QuestionManager) Ask ¶
Ask checks pre-loaded answers or auto-answer mode. Returns ErrQuestionNeeded if no answer is available (caller should suspend).
func (*QuestionManager) PushAnswers ¶
func (qm *QuestionManager) PushAnswers(answers [][]string)
PushAnswers adds a batch of pre-resolved answers to the FIFO queue.
func (*QuestionManager) PushScriptedAnswers ¶
func (qm *QuestionManager) PushScriptedAnswers(answers []string)
PushScriptedAnswers adds raw string answers that get resolved at ask time. Numeric strings (e.g. "6") are resolved to the corresponding 1-based option label. Non-numeric strings are used as-is (custom answers).
func (*QuestionManager) SetAutoAnswer ¶
func (qm *QuestionManager) SetAutoAnswer(auto bool)
SetAutoAnswer enables or disables auto-answer mode. When enabled, empty answers are returned when the queue is exhausted.
type QuestionOption ¶
QuestionOption represents a choice option.
type QuestionRejectedPayload ¶
type QuestionRejectedPayload struct {
SessionID string `json:"sessionID"`
RequestID string `json:"requestID"`
}
QuestionRejectedPayload is the payload for question.rejected events.
type QuestionRepliedPayload ¶
type QuestionRepliedPayload struct {
SessionID string `json:"sessionID"`
RequestID string `json:"requestID"`
Answers [][]string `json:"answers"`
}
QuestionRepliedPayload is the payload for question.replied events.
type SessionCompactedPayload ¶
type SessionCompactedPayload struct {
SessionID string `json:"sessionID"`
}
SessionCompactedPayload is the payload for session.compacted events.
type SessionUpdatedPayload ¶
type SessionUpdatedPayload struct {
SessionID string `json:"sessionID"`
}
SessionUpdatedPayload is the payload for session.updated events.
type ToolContext ¶
ToolContext provides context about which tool call triggered the question.