WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
package chatpipeline
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
)
|
||||
|
||||
// Plugin defines the interface for chat pipeline plugins
|
||||
// Plugins can handle specific events in the chat pipeline
|
||||
type Plugin interface {
|
||||
// OnEvent handles the event with given context and chat management object
|
||||
OnEvent(
|
||||
ctx context.Context,
|
||||
eventType types.EventType,
|
||||
chatManage *types.ChatManage,
|
||||
next func() *PluginError,
|
||||
) *PluginError
|
||||
// ActivationEvents returns the event types this plugin can handle
|
||||
ActivationEvents() []types.EventType
|
||||
}
|
||||
|
||||
// EventManager manages plugins and their event handling
|
||||
type EventManager struct {
|
||||
// Map of event types to registered plugins
|
||||
listeners map[types.EventType][]Plugin
|
||||
// Map of event types to handler functions
|
||||
handlers map[types.EventType]func(context.Context, types.EventType, *types.ChatManage) *PluginError
|
||||
}
|
||||
|
||||
// NewEventManager creates and initializes a new EventManager
|
||||
func NewEventManager() *EventManager {
|
||||
return &EventManager{
|
||||
listeners: make(map[types.EventType][]Plugin),
|
||||
handlers: make(map[types.EventType]func(context.Context, types.EventType, *types.ChatManage) *PluginError),
|
||||
}
|
||||
}
|
||||
|
||||
// Register adds a plugin to the EventManager and sets up its event handlers
|
||||
func (e *EventManager) Register(plugin Plugin) {
|
||||
if e.listeners == nil {
|
||||
e.listeners = make(map[types.EventType][]Plugin)
|
||||
}
|
||||
if e.handlers == nil {
|
||||
e.handlers = make(map[types.EventType]func(context.Context, types.EventType, *types.ChatManage) *PluginError)
|
||||
}
|
||||
for _, eventType := range plugin.ActivationEvents() {
|
||||
e.listeners[eventType] = append(e.listeners[eventType], plugin)
|
||||
e.handlers[eventType] = e.buildHandler(e.listeners[eventType])
|
||||
}
|
||||
}
|
||||
|
||||
// buildHandler constructs a handler chain for the given plugins
|
||||
func (e *EventManager) buildHandler(plugins []Plugin) func(
|
||||
ctx context.Context, eventType types.EventType, chatManage *types.ChatManage,
|
||||
) *PluginError {
|
||||
next := func(context.Context, types.EventType, *types.ChatManage) *PluginError { return nil }
|
||||
for i := len(plugins) - 1; i >= 0; i-- {
|
||||
current := plugins[i]
|
||||
prevNext := next
|
||||
next = func(ctx context.Context, eventType types.EventType, chatManage *types.ChatManage) *PluginError {
|
||||
return current.OnEvent(ctx, eventType, chatManage, func() *PluginError {
|
||||
return prevNext(ctx, eventType, chatManage)
|
||||
})
|
||||
}
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
// Trigger invokes the handler for the specified event type
|
||||
func (e *EventManager) Trigger(ctx context.Context,
|
||||
eventType types.EventType, chatManage *types.ChatManage,
|
||||
) *PluginError {
|
||||
if handler, ok := e.handlers[eventType]; ok {
|
||||
return handler(ctx, eventType, chatManage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PluginError represents an error in plugin execution
|
||||
type PluginError struct {
|
||||
Err error // Original error
|
||||
Description string // Human-readable description
|
||||
ErrorType string // Error type identifier
|
||||
}
|
||||
|
||||
// Predefined plugin errors
|
||||
var (
|
||||
ErrSearchNothing = &PluginError{
|
||||
Description: "No relevant content found",
|
||||
ErrorType: "search_nothing",
|
||||
}
|
||||
ErrSearch = &PluginError{
|
||||
Description: "Failed to search knowledge base",
|
||||
ErrorType: "search_failed",
|
||||
}
|
||||
ErrRerank = &PluginError{
|
||||
Description: "Reranking failed",
|
||||
ErrorType: "rerank_failed",
|
||||
}
|
||||
ErrGetRerankModel = &PluginError{
|
||||
Description: "Failed to get rerank model",
|
||||
ErrorType: "get_rerank_model_failed",
|
||||
}
|
||||
ErrGetChatModel = &PluginError{
|
||||
Description: "Failed to get chat model",
|
||||
ErrorType: "get_chat_model_failed",
|
||||
}
|
||||
ErrTemplateParse = &PluginError{
|
||||
Description: "Failed to parse context template",
|
||||
ErrorType: "template_parse_failed",
|
||||
}
|
||||
ErrTemplateExecute = &PluginError{
|
||||
Description: "Failed to generate search content",
|
||||
ErrorType: "template_execution_failed",
|
||||
}
|
||||
ErrModelCall = &PluginError{
|
||||
Description: "Failed to call model",
|
||||
ErrorType: "model_call_failed",
|
||||
}
|
||||
ErrGetHistory = &PluginError{
|
||||
Description: "Failed to get conversation history",
|
||||
ErrorType: "get_history_failed",
|
||||
}
|
||||
)
|
||||
|
||||
// clone creates a copy of the PluginError
|
||||
func (p *PluginError) clone() *PluginError {
|
||||
return &PluginError{
|
||||
Description: p.Description,
|
||||
ErrorType: p.ErrorType,
|
||||
}
|
||||
}
|
||||
|
||||
// WithError attaches an error to the PluginError and returns a new instance
|
||||
func (p *PluginError) WithError(err error) *PluginError {
|
||||
pp := p.clone()
|
||||
pp.Err = err
|
||||
return pp
|
||||
}
|
||||
Reference in New Issue
Block a user