Help us shape the future of Go! Take the 2026 Go Developer Survey

handler

package
v0.9.1 Latest Latest
Warning

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

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

Documentation

Overview

Package handler defines the AgentEventHandler interface that decouples the agent runner from any specific UI implementation (TUI, ACP, Web, etc.).

All agent-loop events flow through this interface. Concrete implementations adapt the events to the target transport (BubbleTea, WebSocket, ACP JSON-RPC…).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ACPHandler

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

ACPHandler implements AgentEventHandler by sending ACP SessionUpdate notifications through an AgentSideConnection to the connected client.

func NewACPHandler

func NewACPHandler(conn *acp.AgentSideConnection, sessionID acp.SessionId, workDir string) *ACPHandler

NewACPHandler creates a handler bound to an ACP connection and session.

func (*ACPHandler) NotifyToolInProgress added in v0.4.11

func (h *ACPHandler) NotifyToolInProgress(name, args string)

NotifyToolInProgress is used by the approval state when a tool is about to execute without a visible permission prompt (auto-approval or safe tools).

func (*ACPHandler) OnAgentDone

func (h *ACPHandler) OnAgentDone(err error)

func (*ACPHandler) OnAgentStart added in v0.3.2

func (h *ACPHandler) OnAgentStart()

func (*ACPHandler) OnAgentText

func (h *ACPHandler) OnAgentText(text string)

func (*ACPHandler) OnTodoUpdate

func (h *ACPHandler) OnTodoUpdate()

func (*ACPHandler) OnTokenUpdate

func (h *ACPHandler) OnTokenUpdate(info TokenUsage)

func (*ACPHandler) OnToolCall

func (h *ACPHandler) OnToolCall(name, args, einoToolCallID string)

func (*ACPHandler) OnToolResult

func (h *ACPHandler) OnToolResult(name, output, einoToolCallID string, err error)

func (*ACPHandler) RequestApproval

func (h *ACPHandler) RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalResponse, error)

func (*ACPHandler) SetModeChangeCallback added in v0.5.0

func (h *ACPHandler) SetModeChangeCallback(fn func(mode.SessionMode))

SetModeChangeCallback registers a callback invoked whenever the handler changes the session mode (currently the "Allow All" → Full access promotion).

type AgentEventHandler

type AgentEventHandler interface {

	// OnAgentText is called when the agent emits a text chunk (streaming).
	OnAgentText(text string)

	// OnToolCall is called at the beginning of a tool invocation.
	OnToolCall(name, args, toolCallID string)

	// OnToolResult is called when a tool execution completes.
	OnToolResult(name, output, toolCallID string, err error)

	// OnTodoUpdate is called when the todo store is mutated.
	OnTodoUpdate()

	// OnAgentStart is called when the agent begins processing a user prompt,
	// before any LLM call is made. Use this to show a "thinking" / "working"
	// indicator immediately, rather than waiting for the first text chunk.
	OnAgentStart()

	// OnAgentDone is called when the agent loop finishes (err may be nil).
	OnAgentDone(err error)

	// OnTokenUpdate reports cumulative token usage after a run.
	OnTokenUpdate(info TokenUsage)

	// RequestApproval asks the UI for tool-execution permission.
	// It blocks until the user responds or ctx is cancelled.
	// Returns (approved, newMode, error).
	RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalResponse, error)
}

AgentEventHandler is the primary abstraction between the agent runner and the presentation layer. It covers three concerns:

  1. Output events — one-way notifications from agent to UI.
  2. Approval flow — bidirectional: agent requests permission, UI responds.
  3. Lifecycle — done signals, token usage, etc.

Implementations must be safe for concurrent use; the runner may call methods from multiple goroutines (e.g. streaming text while a tool result arrives).

type ApprovalMode

type ApprovalMode int

ApprovalMode mirrors tui.ApprovalMode so that handler consumers don't import tui.

const (
	ModeManual ApprovalMode = iota
	ModeAuto
)

type ApprovalRequest

type ApprovalRequest struct {
	ToolName    string
	ToolArgs    string
	ToolCallID  string // unique ID of this tool invocation (from the LLM)
	IsExternal  bool   // true when accessing paths outside workpath
	WorkerName  string // non-empty for teammate agents
	WorkerColor string
}

ApprovalRequest describes a tool that needs user permission.

type ApprovalResponse

type ApprovalResponse struct {
	Approved bool
	Mode     ApprovalMode
}

ApprovalResponse is what the UI returns for an approval request.

type NotifyingHandler added in v0.1.1

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

NotifyingHandler wraps another AgentEventHandler and adds delayed notification capabilities for approval requests and agent completion events. It also supports a list of channel.Notifier instances for lightweight one-way status pushes (e.g. BLE IoT devices).

func NewNotifyingHandler added in v0.1.1

func NewNotifyingHandler(inner AgentEventHandler, delay time.Duration) *NotifyingHandler

NewNotifyingHandler creates a handler that wraps inner and can fire external notifications for approvals (after a delay) and agent completion.

func (*NotifyingHandler) AddNotifier added in v0.3.1

func (h *NotifyingHandler) AddNotifier(n channel.Notifier)

AddNotifier registers a lightweight notifier (e.g. BLE device). Notifiers receive automatic status pushes for agent lifecycle events.

func (*NotifyingHandler) CloseNotifiers added in v0.3.1

func (h *NotifyingHandler) CloseNotifiers()

CloseNotifiers closes all registered notifiers.

func (*NotifyingHandler) OnAgentDone added in v0.1.1

func (h *NotifyingHandler) OnAgentDone(err error)

func (*NotifyingHandler) OnAgentStart added in v0.3.2

func (h *NotifyingHandler) OnAgentStart()

func (*NotifyingHandler) OnAgentText added in v0.1.1

func (h *NotifyingHandler) OnAgentText(text string)

func (*NotifyingHandler) OnTodoUpdate added in v0.1.1

func (h *NotifyingHandler) OnTodoUpdate()

func (*NotifyingHandler) OnTokenUpdate added in v0.1.1

func (h *NotifyingHandler) OnTokenUpdate(info TokenUsage)

func (*NotifyingHandler) OnToolCall added in v0.1.1

func (h *NotifyingHandler) OnToolCall(name, args, toolCallID string)

func (*NotifyingHandler) OnToolResult added in v0.1.1

func (h *NotifyingHandler) OnToolResult(name, output, toolCallID string, err error)

func (*NotifyingHandler) RequestApproval added in v0.1.1

func (h *NotifyingHandler) RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalResponse, error)

func (*NotifyingHandler) SetApprovalNotifier added in v0.1.1

func (h *NotifyingHandler) SetApprovalNotifier(fn func(toolName, toolArgs string))

SetApprovalNotifier sets the callback fired when an approval is not resolved within the delay.

func (*NotifyingHandler) SetDoneNotifier added in v0.1.1

func (h *NotifyingHandler) SetDoneNotifier(fn func(summary string, err error))

SetDoneNotifier sets the callback fired when the agent finishes.

type TUIHandler

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

TUIHandler adapts AgentEventHandler to a BubbleTea *tea.Program. It translates every interface method into a p.Send(msg) call using the existing TUI message types.

func NewTUIHandler

func NewTUIHandler(p *tea.Program) *TUIHandler

NewTUIHandler creates a handler backed by a BubbleTea program.

func (*TUIHandler) OnAgentDone

func (h *TUIHandler) OnAgentDone(err error)

func (*TUIHandler) OnAgentStart added in v0.3.2

func (h *TUIHandler) OnAgentStart()

func (*TUIHandler) OnAgentText

func (h *TUIHandler) OnAgentText(text string)

func (*TUIHandler) OnTodoUpdate

func (h *TUIHandler) OnTodoUpdate()

func (*TUIHandler) OnTokenUpdate

func (h *TUIHandler) OnTokenUpdate(info TokenUsage)

func (*TUIHandler) OnToolCall

func (h *TUIHandler) OnToolCall(name, args, _ string)

func (*TUIHandler) OnToolResult

func (h *TUIHandler) OnToolResult(name, output, _ string, err error)

func (*TUIHandler) RequestApproval

func (h *TUIHandler) RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalResponse, error)

func (*TUIHandler) SetProgram

func (h *TUIHandler) SetProgram(p *tea.Program)

SetProgram replaces the underlying BubbleTea program (e.g. after the program is created lazily).

type TokenUsage

type TokenUsage struct {
	TotalTokens       int64
	PromptTokens      int64
	CompletionTokens  int64
	CachedTokens      int64
	ReasoningTokens   int64
	CacheWriteTokens  int64
	CallCount         int64
	CacheHitRate      float64
	CacheSupported    bool
	ModelContextLimit int // 0 if unknown
}

TokenUsage carries token usage info to the UI surfaces.

TotalTokens is the LAST call's total — i.e. current context-window occupancy, used to drive the context-usage bar. The remaining token counters (Prompt/Completion/Cached/Reasoning/CacheWrite/CallCount) are CUMULATIVE for the run's tracker, and CacheHitRate is the cumulative cached/prompt ratio. CacheSupported is false when the provider never reported any cached tokens, so the UI can show "—" instead of a misleading 0%.

NOTE: the field order/types here must stay identical to WebTokenData (internal/handler/web.go) so OnTokenUpdate's direct struct conversion keeps compiling.

type ToolDisplayInfo added in v0.3.3

type ToolDisplayInfo struct {
	Title    string `json:"title"`              // Human-readable tool name (e.g. "Read", "Edit", "Shell")
	Subtitle string `json:"subtitle,omitempty"` // Context info (file path, command description, pattern)
	Icon     string `json:"icon,omitempty"`     // Icon identifier
	Category string `json:"category,omitempty"` // "context" (read-only), "mutation", "execution"
}

ToolDisplayInfo carries human-readable tool metadata for UI rendering.

type WebApprovalRequestData

type WebApprovalRequestData struct {
	ID         string `json:"id"`
	ToolName   string `json:"tool_name"`
	ToolArgs   string `json:"tool_args"`
	IsExternal bool   `json:"is_external"`
}

WebApprovalRequestData carries an approval request.

type WebAskUserRequestData added in v0.5.2

type WebAskUserRequestData struct {
	ID        string                  `json:"id"`
	Questions []tools.AskUserQuestion `json:"questions"`
}

WebAskUserRequestData carries an ask_user question request to web clients.

type WebDoneData

type WebDoneData struct {
	Error string `json:"error,omitempty"`
}

WebDoneData signals agent completion.

type WebEvent

type WebEvent struct {
	Event string `json:"event"`
	Data  any    `json:"data"`
}

WebEvent is an event sent from the agent to web clients.

type WebHandler

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

WebHandler implements AgentEventHandler by sending events to web clients through a channel-based event broker.

func NewWebHandler

func NewWebHandler() *WebHandler

NewWebHandler creates a handler that sends events to the given channel.

func (*WebHandler) Emit added in v0.1.1

func (h *WebHandler) Emit(event string, data any)

Emit sends a custom event to all connected web clients.

func (*WebHandler) Events

func (h *WebHandler) Events() <-chan WebEvent

Events returns the read-only event channel.

func (*WebHandler) OnAgentDone

func (h *WebHandler) OnAgentDone(err error)

func (*WebHandler) OnAgentStart added in v0.3.2

func (h *WebHandler) OnAgentStart()

func (*WebHandler) OnAgentText

func (h *WebHandler) OnAgentText(text string)

func (*WebHandler) OnSubagentEvent

func (h *WebHandler) OnSubagentEvent(name, agentType string, done bool, result string, err error)

func (*WebHandler) OnSubagentProgress

func (h *WebHandler) OnSubagentProgress(agentName, event, toolName, detail string)

func (*WebHandler) OnTodoUpdate

func (h *WebHandler) OnTodoUpdate()

func (*WebHandler) OnTokenUpdate

func (h *WebHandler) OnTokenUpdate(info TokenUsage)

func (*WebHandler) OnToolCall

func (h *WebHandler) OnToolCall(name, args, toolCallID string)

func (*WebHandler) OnToolResult

func (h *WebHandler) OnToolResult(name, output, toolCallID string, err error)

func (*WebHandler) PendingApprovalRequests added in v0.6.2

func (h *WebHandler) PendingApprovalRequests() []WebApprovalRequestData

PendingApprovalRequests returns the still-unanswered approval requests so a reloaded/reconnecting client can re-surface the approval card (the approval_request WS event is fire-once and ephemeral). Without this, a page refresh or WS reconnect while an approval is pending would drop the card and leave the agent blocked forever. Mirrors PendingAskUserRequests.

func (*WebHandler) PendingAskUserRequests added in v0.5.2

func (h *WebHandler) PendingAskUserRequests() []WebAskUserRequestData

PendingAskUserRequests returns the still-unanswered ask_user requests so a reloaded/reconnecting client can re-surface the question (the ask_user_request WS event is fire-once and ephemeral). Without this, a page refresh while a question is pending would leave the agent blocked with no way to answer.

func (*WebHandler) RequestApproval

func (h *WebHandler) RequestApproval(ctx context.Context, req ApprovalRequest) (ApprovalResponse, error)

func (*WebHandler) RequestAskUser added in v0.5.2

func (h *WebHandler) RequestAskUser(ctx context.Context, questions []tools.AskUserQuestion) (tools.AskUserBatchResponse, error)

RequestAskUser emits the question(s) to web clients and blocks until the user answers (via the /api/ask endpoint → ResolveAskUser) or the context is cancelled. It mirrors RequestApproval: a per-request id keys a one-shot response channel so the API handler can route the answer back. This is wired into the ask_user tool's BatchRequestFn for the web frontend.

func (*WebHandler) ResolveApproval

func (h *WebHandler) ResolveApproval(id string, approved, approveAll bool) error

ResolveApproval resolves a pending approval request. Called by API handler. approveAll distinguishes "approve all" (promote the session to auto-approve, like the TUI's "Approve All" and ACP's "Allow Always") from a plain "approve once" that leaves the session mode untouched. Previously every approve was treated as auto, silently flipping the whole session to Full access on a single Allow click.

func (*WebHandler) ResolveAskUser added in v0.5.2

func (h *WebHandler) ResolveAskUser(id string, resp tools.AskUserBatchResponse) error

ResolveAskUser delivers the user's answers to a pending ask_user request. Called by the API handler when the frontend submits answers.

type WebSubagentData

type WebSubagentData struct {
	Name      string `json:"name"`
	AgentType string `json:"agent_type"`
	Done      bool   `json:"done"`
	Result    string `json:"result,omitempty"`
	Error     string `json:"error,omitempty"`
}

WebSubagentData carries subagent lifecycle events.

type WebSubagentProgressData

type WebSubagentProgressData struct {
	AgentName string `json:"agent_name"`
	Event     string `json:"event"` // "tool_call" or "tool_result"
	ToolName  string `json:"tool_name"`
	Detail    string `json:"detail"`
}

WebSubagentProgressData carries intermediate subagent tool call/result events.

type WebTextData

type WebTextData struct {
	Text string `json:"text"`
}

WebTextData carries a streaming text chunk.

type WebTokenData

type WebTokenData struct {
	TotalTokens       int64   `json:"total_tokens"`
	PromptTokens      int64   `json:"prompt_tokens"`
	CompletionTokens  int64   `json:"completion_tokens"`
	CachedTokens      int64   `json:"cached_tokens"`
	ReasoningTokens   int64   `json:"reasoning_tokens"`
	CacheWriteTokens  int64   `json:"cache_write_tokens"`
	CallCount         int64   `json:"call_count"`
	CacheHitRate      float64 `json:"cache_hit_rate"`
	CacheSupported    bool    `json:"cache_supported"`
	ModelContextLimit int     `json:"model_context_limit"`
}

WebTokenData carries token usage to the browser. Field order/types MUST match handler.TokenUsage so OnTokenUpdate's WebTokenData(info) conversion compiles. total_tokens is current context occupancy (last call); the rest are cumulative for the session.

type WebToolCallData

type WebToolCallData struct {
	Name        string           `json:"name"`
	Args        string           `json:"args"`
	ToolCallID  string           `json:"tool_call_id,omitempty"`
	DisplayInfo *ToolDisplayInfo `json:"display_info,omitempty"`
}

WebToolCallData carries tool invocation info.

type WebToolResultData

type WebToolResultData struct {
	Name          string `json:"name"`
	Output        string `json:"output"`
	DisplayOutput string `json:"display_output,omitempty"` // clean output for UI display
	Error         string `json:"error,omitempty"`
	ToolCallID    string `json:"tool_call_id,omitempty"`
}

WebToolResultData carries tool completion info.

Jump to

Keyboard shortcuts

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