Documentation
¶
Index ¶
- func Clear()
- func Emit(ctx context.Context, event Event) error
- func EmitAndWait(ctx context.Context, event Event) error
- func HasHandlers(eventType EventType) bool
- func NewEventBusAdapter(bus *EventBus) types.EventBusInterface
- func Off(eventType EventType)
- func On(eventType EventType, handler EventHandler)
- func SetGlobalEventBus(bus *EventBus)
- type AgentActionData
- type AgentCompleteData
- type AgentFinalAnswerData
- type AgentPlanData
- type AgentQueryData
- type AgentReferencesData
- type AgentReflectionData
- type AgentStepData
- type AgentThoughtData
- type AgentToolCallData
- type AgentToolResultData
- type ChatData
- type CommandOutputData
- type ContextCompactedData
- type ErrorData
- type Event
- type EventBus
- func (eb *EventBus) AsEventBusInterface() types.EventBusInterface
- func (eb *EventBus) Clear()
- func (eb *EventBus) Emit(ctx context.Context, event Event) error
- func (eb *EventBus) EmitAndWait(ctx context.Context, event Event) error
- func (eb *EventBus) GetHandlerCount(eventType EventType) int
- func (eb *EventBus) HasHandlers(eventType EventType) bool
- func (eb *EventBus) Off(eventType EventType)
- func (eb *EventBus) On(eventType EventType, handler EventHandler)
- type EventBusAdapter
- type EventHandler
- type EventType
- type MCPOAuthRequiredData
- type MCPOAuthResolvedData
- type MemoryRecalledData
- type MergeData
- type Middleware
- type PanicError
- type QueryData
- type RerankData
- type RetrievalData
- type SessionTitleData
- type StopData
- type ToolApprovalRequiredData
- type ToolApprovalResolvedData
- type UserMessageInjectedData
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EmitAndWait ¶
EmitAndWait publishes an event to the global event bus and waits for all handlers
func HasHandlers ¶
HasHandlers checks if there are any handlers registered for an event type
func NewEventBusAdapter ¶
func NewEventBusAdapter(bus *EventBus) types.EventBusInterface
NewEventBusAdapter creates a new adapter for EventBus
func Off ¶
func Off(eventType EventType)
Off removes all handlers for a specific event type from the global event bus
func On ¶
func On(eventType EventType, handler EventHandler)
On registers an event handler on the global event bus
func SetGlobalEventBus ¶
func SetGlobalEventBus(bus *EventBus)
SetGlobalEventBus sets the global event bus instance This is useful for testing or custom configurations
Types ¶
type AgentActionData ¶
type AgentActionData struct {
Iteration int `json:"iteration"`
ToolName string `json:"tool_name"`
ToolInput map[string]interface{} `json:"tool_input"`
ToolOutput string `json:"tool_output"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Duration int64 `json:"duration_ms"`
}
AgentActionData represents agent tool execution event data
type AgentCompleteData ¶
type AgentCompleteData struct {
SessionID string `json:"session_id"`
TotalSteps int `json:"total_steps"`
FinalAnswer string `json:"final_answer"`
KnowledgeRefs []interface{} `json:"knowledge_refs,omitempty"` // []*types.SearchResult
AgentSteps interface{} `json:"agent_steps,omitempty"` // []types.AgentStep - detailed execution steps
Usage interface{} `json:"usage,omitempty"` // *types.TokenUsage - LLM token usage aggregated over the turn
ModelID string `json:"model_id,omitempty"` // Chat model whose calls produced Usage
TotalDurationMs int64 `json:"total_duration_ms"`
MessageID string `json:"message_id,omitempty"` // Assistant message ID
RequestID string `json:"request_id,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
AgentCompleteData represents agent completion event data
type AgentFinalAnswerData ¶
type AgentFinalAnswerData struct {
Content string `json:"content"`
Done bool `json:"done"`
IsFallback bool `json:"is_fallback,omitempty"` // True when response is a fallback (no knowledge base match)
// Truncated marks an answer the provider cut off at the completion-token
// cap. The text is what the model had produced when the cap hit, not a
// finished answer, so a client should say so rather than present it as
// complete. Carried on both the content event and the Done marker,
// because a live-streamed answer only learns of the cap at the close.
Truncated bool `json:"truncated,omitempty"`
}
AgentFinalAnswerData represents final answer streaming data
type AgentPlanData ¶
type AgentPlanData struct {
Query string `json:"query"`
Plan []string `json:"plan"` // Step descriptions
Duration int64 `json:"duration_ms,omitempty"`
}
AgentPlanData represents agent planning event data
type AgentQueryData ¶
type AgentQueryData struct {
SessionID string `json:"session_id"`
Query string `json:"query"`
RequestID string `json:"request_id,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
AgentQueryData represents agent query event data
type AgentReferencesData ¶
type AgentReferencesData struct {
References interface{} `json:"references"` // []*types.SearchResult
Iteration int `json:"iteration"`
}
AgentReferencesData represents knowledge references data
type AgentReflectionData ¶
type AgentReflectionData struct {
ToolCallID string `json:"tool_call_id"` // Tool call ID for tracking
Content string `json:"content"`
Iteration int `json:"iteration"`
Done bool `json:"done"` // Whether streaming is complete
}
AgentReflectionData represents agent reflection data
type AgentStepData ¶
type AgentStepData struct {
Iteration int `json:"iteration"`
Thought string `json:"thought"`
ToolCalls interface{} `json:"tool_calls"` // []types.ToolCall
Duration int64 `json:"duration_ms"`
}
AgentStepData represents agent step event data
type AgentThoughtData ¶
type AgentThoughtData struct {
Content string `json:"content"`
Iteration int `json:"iteration"`
Done bool `json:"done"`
}
AgentThoughtData represents agent thought streaming data
type AgentToolCallData ¶
type AgentToolCallData struct {
ToolCallID string `json:"tool_call_id"` // Tool call ID for tracking
ToolName string `json:"tool_name"`
Arguments map[string]any `json:"arguments,omitempty"`
Iteration int `json:"iteration"`
Hint string `json:"hint,omitempty"` // Human-readable tool hint, e.g. `web_search("query")`
}
AgentToolCallData represents agent tool call notification data
type AgentToolResultData ¶
type AgentToolResultData struct {
ToolCallID string `json:"tool_call_id"` // Tool call ID for tracking
ToolName string `json:"tool_name"`
Output string `json:"output"`
Error string `json:"error,omitempty"`
Success bool `json:"success"`
Duration int64 `json:"duration_ms,omitempty"`
Iteration int `json:"iteration"`
Data map[string]interface{} `json:"data,omitempty"` // Structured data from tool result (e.g., display_type, formatted results)
}
AgentToolResultData represents agent tool execution result data
type ChatData ¶
type ChatData struct {
Query string `json:"query"`
ModelID string `json:"model_id"`
Response string `json:"response,omitempty"`
StreamChunk string `json:"stream_chunk,omitempty"`
TokenCount int `json:"token_count,omitempty"`
Duration int64 `json:"duration_ms,omitempty"`
IsStream bool `json:"is_stream"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
ChatData represents chat completion event data
type CommandOutputData ¶
type CommandOutputData struct {
ToolCallID string `json:"tool_call_id"`
Command string `json:"command"`
StartedAt time.Time `json:"started_at"`
Output string `json:"output"`
Done bool `json:"done"`
}
CommandOutputData is a cumulative tail, so reconnect/replay needs no byte offsets and a missed update does not corrupt the displayed log.
type ContextCompactedData ¶
type ContextCompactedData struct {
Reason string `json:"reason"` // threshold | overflow
Round int `json:"round"`
TokensBefore int `json:"tokens_before"`
TokensAfter int `json:"tokens_after"`
MessagesBefore int `json:"messages_before"`
MessagesAfter int `json:"messages_after"`
Summary string `json:"summary"`
// Degraded marks a summary that came from the mechanical archive because
// the summarizer failed.
Degraded bool `json:"degraded,omitempty"`
// SplitTurn marks a cut that landed inside a single turn.
SplitTurn bool `json:"split_turn,omitempty"`
}
ContextCompactedData reports that older conversation was replaced by a summary. Compaction changes what the agent remembers, so it is shown rather than hidden: an answer that forgets an earlier instruction is otherwise indistinguishable from the model ignoring it.
type ErrorData ¶
type ErrorData struct {
Error string `json:"error"`
ErrorCode string `json:"error_code,omitempty"`
Stage string `json:"stage"` // 错误发生的阶段
SessionID string `json:"session_id"`
Query string `json:"query,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
ErrorData represents error event data
type Event ¶
type Event struct {
ID string // 事件ID (自动生成UUID,用于流式更新追踪)
Type EventType // 事件类型
SessionID string // 会话ID
Data interface{} // 事件数据
Metadata map[string]interface{} // 事件元数据
RequestID string // 请求ID
}
Event represents an event in the system
func (Event) WithMetadata ¶
WithMetadata adds metadata to the event
func (Event) WithRequestID ¶
WithRequestID sets the request ID for the event
func (Event) WithSessionID ¶
WithSessionID sets the session ID for the event
type EventBus ¶
type EventBus struct {
// contains filtered or unexported fields
}
EventBus manages event publishing and subscription
Example (Basic) ¶
Example: Basic usage of event system
ctx := context.Background()
bus := NewEventBus()
// Register a handler
bus.On(EventQueryReceived, func(ctx context.Context, event Event) error {
fmt.Printf("Query received: %v\n", event.Data)
return nil
})
// Emit an event
event := NewEvent(EventQueryReceived, QueryData{
OriginalQuery: "What is RAG?",
SessionID: "session-123",
})
_ = bus.Emit(ctx, event)
Output: Query received: {What is RAG? session-123 map[]}
Example (Middleware) ¶
Example: Using middleware
ctx := context.Background()
bus := NewEventBus()
// Create a handler with middleware
handler := func(ctx context.Context, event Event) error {
data := event.Data.(QueryData)
fmt.Printf("Processing query: %s\n", data.OriginalQuery)
return nil
}
// Apply middleware
handlerWithMiddleware := ApplyMiddleware(
handler,
WithTiming(),
WithRecovery(),
)
bus.On(EventQueryReceived, handlerWithMiddleware)
event := NewEvent(EventQueryReceived, QueryData{
OriginalQuery: "What is RAG?",
})
_ = bus.Emit(ctx, event)
Output: Processing query: What is RAG?
Example (Pipeline) ¶
Example: Query processing pipeline with events
ctx := context.Background()
bus := NewEventBus()
// Step 1: Query received
bus.On(EventQueryReceived, func(ctx context.Context, event Event) error {
data := event.Data.(QueryData)
fmt.Printf("1. Query received: %s\n", data.OriginalQuery)
return nil
})
// Step 2: Query rewrite
bus.On(EventQueryRewrite, func(ctx context.Context, event Event) error {
data := event.Data.(QueryData)
fmt.Printf("2. Rewriting query: %s\n", data.OriginalQuery)
return nil
})
// Step 3: Retrieval
bus.On(EventRetrievalStart, func(ctx context.Context, event Event) error {
data := event.Data.(RetrievalData)
fmt.Printf("3. Starting retrieval for: %s\n", data.Query)
return nil
})
// Step 4: Rerank
bus.On(EventRerankStart, func(ctx context.Context, event Event) error {
data := event.Data.(RerankData)
fmt.Printf("4. Starting rerank for: %s\n", data.Query)
return nil
})
// Simulate pipeline
sessionID := "session-123"
_ = bus.Emit(ctx, NewEvent(EventQueryReceived, QueryData{
OriginalQuery: "What is RAG?",
SessionID: sessionID,
}))
_ = bus.Emit(ctx, NewEvent(EventQueryRewrite, QueryData{
OriginalQuery: "What is RAG?",
SessionID: sessionID,
}))
_ = bus.Emit(ctx, NewEvent(EventRetrievalStart, RetrievalData{
Query: "What is Retrieval Augmented Generation?",
KnowledgeBaseID: "kb-1",
TopK: 10,
}))
_ = bus.Emit(ctx, NewEvent(EventRerankStart, RerankData{
Query: "What is Retrieval Augmented Generation?",
InputCount: 10,
OutputCount: 5,
ModelID: "rerank-model-1",
}))
Output: 1. Query received: What is RAG? 2. Rewriting query: What is RAG? 3. Starting retrieval for: What is Retrieval Augmented Generation? 4. Starting rerank for: What is Retrieval Augmented Generation?
func GetGlobalEventBus ¶
func GetGlobalEventBus() *EventBus
GetGlobalEventBus returns the global event bus instance It uses singleton pattern to ensure only one instance exists
func NewAsyncEventBus ¶
func NewAsyncEventBus() *EventBus
NewAsyncEventBus creates a new EventBus with async mode enabled
func (*EventBus) AsEventBusInterface ¶
func (eb *EventBus) AsEventBusInterface() types.EventBusInterface
AsEventBusInterface converts *EventBus to types.EventBusInterface
func (*EventBus) Emit ¶
Emit publishes an event to all registered handlers Returns error if any handler fails (in sync mode) Automatically generates an ID for the event if not provided (from source)
func (*EventBus) EmitAndWait ¶
EmitAndWait publishes an event and waits for all handlers to complete This method works in both sync and async mode Automatically generates an ID for the event if not provided (from source)
func (*EventBus) GetHandlerCount ¶
GetHandlerCount returns the number of handlers for a specific event type
func (*EventBus) HasHandlers ¶
HasHandlers checks if there are any handlers registered for an event type
func (*EventBus) On ¶
func (eb *EventBus) On(eventType EventType, handler EventHandler)
On registers an event handler for a specific event type Multiple handlers can be registered for the same event type
type EventBusAdapter ¶
type EventBusAdapter struct {
// contains filtered or unexported fields
}
EventBusAdapter adapts *EventBus to types.EventBusInterface This allows EventBus to be used through the interface without circular dependencies
func (*EventBusAdapter) On ¶
func (a *EventBusAdapter) On(eventType types.EventType, handler types.EventHandler)
On registers an event handler for a specific event type
type EventHandler ¶
EventHandler is a function that handles events
func ApplyMiddleware ¶
func ApplyMiddleware(handler EventHandler, middlewares ...Middleware) EventHandler
ApplyMiddleware applies middleware to an event handler
type EventType ¶
type EventType string
EventType represents the type of event in the system
const ( // Query processing events EventQueryReceived EventType = "query.received" // 用户查询到达 EventQueryValidated EventType = "query.validated" // 查询验证完成 EventQueryPreprocess EventType = "query.preprocess" // 查询预处理 EventQueryRewrite EventType = "query.rewrite" // 查询改写 EventQueryRewritten EventType = "query.rewritten" // 查询改写完成 // Retrieval events EventRetrievalStart EventType = "retrieval.start" // 检索开始 EventRetrievalVector EventType = "retrieval.vector" // 向量检索 EventRetrievalKeyword EventType = "retrieval.keyword" // 关键词检索 EventRetrievalEntity EventType = "retrieval.entity" // 实体检索 EventRetrievalComplete EventType = "retrieval.complete" // 检索完成 // Rerank events EventRerankStart EventType = "rerank.start" // 排序开始 EventRerankComplete EventType = "rerank.complete" // 排序完成 // Merge events EventMergeStart EventType = "merge.start" // 合并开始 EventMergeComplete EventType = "merge.complete" // 合并完成 // Chat completion events EventChatStart EventType = "chat.start" // 聊天生成开始 EventChatComplete EventType = "chat.complete" // 聊天生成完成 EventChatStream EventType = "chat.stream" // 聊天流式输出 // Agent events EventAgentQuery EventType = "agent.query" // Agent 查询开始 EventAgentPlan EventType = "agent.plan" // Agent 计划生成 EventAgentStep EventType = "agent.step" // Agent 步骤执行 EventAgentTool EventType = "agent.tool" // Agent 工具调用 EventAgentComplete EventType = "agent.complete" // Agent 完成 // Agent streaming events (for real-time feedback) EventAgentThought EventType = "thought" // Agent 思考过程 EventAgentCommandOutput EventType = "command_output" // bounded command output EventAgentToolCall EventType = "tool_call" // 工具调用通知 EventAgentToolResult EventType = "tool_result" // 工具结果 EventAgentReflection EventType = "reflection" // Agent 反思 EventAgentReferences EventType = "references" // 知识引用 EventAgentFinalAnswer EventType = "final_answer" // 最终答案 // MCP tool human approval (issue #1173) EventToolApprovalRequired EventType = "tool_approval_required" EventToolApprovalResolved EventType = "tool_approval_resolved" // MCP OAuth in-conversation authorization prompt: emitted when an // OAuth-enabled MCP service is invoked but the current user has not // authorized it yet. The agent pauses until the user authorizes (or the // wait times out / is canceled). EventMCPOAuthRequired EventType = "mcp_oauth_required" EventMCPOAuthResolved EventType = "mcp_oauth_resolved" // Error events EventError EventType = "error" // 错误事件 // Long-term memory recalled for this turn. Emitted once, before the answer // streams, so the UI can show which memories the answer saw. EventMemoryRecalled EventType = "memory_recalled" // EventContextCompacted is emitted when older conversation was summarized // away to fit the context window. EventContextCompacted EventType = "context_compacted" // EventUserMessageInjected is emitted when a message the user appended // while the run was in flight was accepted into the running turn (see // agent drainSteerMessages). EventUserMessageInjected EventType = "user_message_injected" // Session events EventSessionTitle EventType = "session_title" // 会话标题更新 // Control events EventStop EventType = "stop" // 停止对话生成 )
type MCPOAuthRequiredData ¶
type MCPOAuthRequiredData struct {
PendingID string `json:"pending_id"`
TenantID uint64 `json:"tenant_id"`
SessionID string `json:"session_id"`
AssistantMessageID string `json:"assistant_message_id"`
ServiceID string `json:"service_id"`
ServiceName string `json:"service_name"`
MCPToolName string `json:"mcp_tool_name"`
TimeoutSeconds int `json:"timeout_seconds"`
RequestedAtUnix int64 `json:"requested_at"`
ToolCallID string `json:"tool_call_id"`
RequestID string `json:"request_id,omitempty"`
}
MCPOAuthRequiredData is emitted when an OAuth-enabled MCP service is invoked during a conversation but the current user has not authorized it yet. The UI surfaces an "Authorize" card; the agent pauses until the user authorizes.
type MCPOAuthResolvedData ¶
type MCPOAuthResolvedData struct {
PendingID string `json:"pending_id"`
ServiceID string `json:"service_id"`
Authorized bool `json:"authorized"`
Reason string `json:"reason,omitempty"`
TimedOut bool `json:"timed_out,omitempty"`
Canceled bool `json:"canceled,omitempty"`
}
MCPOAuthResolvedData confirms the outcome of an in-conversation OAuth prompt (authorized / timeout / cancel).
type MemoryRecalledData ¶
type MemoryRecalledData struct {
Memories interface{} `json:"memories"`
}
MemoryRecalledData carries the long-term memories injected into this turn. Memories is []types.UsedMemory, kept as interface{} for the same reason AgentReferencesData does: the event package stays free of a types import.
type MergeData ¶
type MergeData struct {
InputCount int `json:"input_count"`
OutputCount int `json:"output_count"`
MergeType string `json:"merge_type"` // dedup, fusion, etc.
Results interface{} `json:"results,omitempty"`
Duration int64 `json:"duration_ms,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
MergeData represents merge event data
type Middleware ¶
type Middleware func(EventHandler) EventHandler
Middleware is a function that wraps an EventHandler
func Chain ¶
func Chain(middlewares ...Middleware) Middleware
Chain combines multiple middlewares into a single middleware
func WithLogging ¶
func WithLogging() Middleware
WithLogging creates a middleware that logs event handling
func WithRecovery ¶
func WithRecovery() Middleware
WithRecovery creates a middleware that recovers from panics
func WithTiming ¶
func WithTiming() Middleware
WithTiming creates a middleware that tracks event handling duration
type PanicError ¶
type PanicError struct {
Panic interface{}
}
PanicError represents a panic that occurred in an event handler
func (*PanicError) Error ¶
func (e *PanicError) Error() string
type QueryData ¶
type QueryData struct {
OriginalQuery string `json:"original_query"`
RewrittenQuery string `json:"rewritten_query,omitempty"`
SessionID string `json:"session_id"`
UserID string `json:"user_id,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
QueryData represents query-related event data
type RerankData ¶
type RerankData struct {
Query string `json:"query"`
InputCount int `json:"input_count"` // 输入的候选数量
OutputCount int `json:"output_count"` // 输出的结果数量
ModelID string `json:"model_id"`
Threshold float64 `json:"threshold"`
Results interface{} `json:"results,omitempty"`
Duration int64 `json:"duration_ms,omitempty"` // 排序耗时(毫秒)
Extra map[string]interface{} `json:"extra,omitempty"`
}
RerankData represents reranking event data
type RetrievalData ¶
type RetrievalData struct {
Query string `json:"query"`
KnowledgeBaseID string `json:"knowledge_base_id"`
TopK int `json:"top_k"`
Threshold float64 `json:"threshold"`
RetrievalType string `json:"retrieval_type"` // vector, keyword, entity
ResultCount int `json:"result_count"`
Results interface{} `json:"results,omitempty"`
Duration int64 `json:"duration_ms,omitempty"` // 检索耗时(毫秒)
Extra map[string]interface{} `json:"extra,omitempty"`
}
RetrievalData represents retrieval event data
type SessionTitleData ¶
SessionTitleData represents session title update data
type StopData ¶
type StopData struct {
SessionID string `json:"session_id"`
MessageID string `json:"message_id"`
Reason string `json:"reason,omitempty"` // Optional reason for stopping
}
StopData represents stop generation request data
type ToolApprovalRequiredData ¶
type ToolApprovalRequiredData struct {
PendingID string `json:"pending_id"`
TenantID uint64 `json:"tenant_id"`
SessionID string `json:"session_id"`
AssistantMessageID string `json:"assistant_message_id"`
ServiceID string `json:"service_id"`
ServiceName string `json:"service_name"`
MCPToolName string `json:"mcp_tool_name"`
RegisteredToolName string `json:"registered_tool_name"`
Description string `json:"description"`
Args interface{} `json:"args,omitempty"`
ArgsJSON string `json:"args_json,omitempty"`
TimeoutSeconds int `json:"timeout_seconds"`
RequestedAtUnix int64 `json:"requested_at"`
ToolCallID string `json:"tool_call_id"`
RequestID string `json:"request_id,omitempty"`
}
ToolApprovalRequiredData is emitted when an MCP tool marked dangerous is about to run.
type ToolApprovalResolvedData ¶
type ToolApprovalResolvedData struct {
PendingID string `json:"pending_id"`
Approved bool `json:"approved"`
Reason string `json:"reason,omitempty"`
TimedOut bool `json:"timed_out,omitempty"`
Canceled bool `json:"canceled,omitempty"`
}
ToolApprovalResolvedData confirms the user decision (or timeout/cancel).
type UserMessageInjectedData ¶
type UserMessageInjectedData struct {
SteerID string `json:"steer_id"` // Correlates with the queued steer event
Content string `json:"content"` // The injected text, as sent to the model
MessageID string `json:"message_id"` // Durable assistant message of the run
UserMessageID string `json:"user_message_id,omitempty"`
}
UserMessageInjectedData reports that a message the user appended while the run was in flight was accepted into the running turn: a user-role row has been persisted under the run's request ID and the text was appended to the agent's message list, so the next LLM call already sees it.