feat: RAG, memory, plugins, lessons, file editor, split panes, Markdown rendering, PWA + UI overhaul
All checks were successful
Stable Release / stable (push) Successful in 1m34s
All checks were successful
Stable Release / stable (push) Successful in 1m34s
Major additions: - RAG pipeline (indexing, chunking, search) with sidebar upload button - Memory system with CRUD API - Plugins and lessons modules - MCP discovery and MCP server - Advanced skills (auto-create, conditional, improver) - Agent browser/image support, delegate, sessions - File editor with CodeMirror in split panes - Markdown rendering via react-markdown + KaTeX + highlight.js - Raw markdown toggle - PWA manifest + service worker - Extension UI redesign with new design tokens and studio-style chat - Pipeline API for chat streaming - Mobile responsive layout 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
94
internal/plugins/hooks.go
Normal file
94
internal/plugins/hooks.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sync"
|
||||
|
||||
"github.com/muyue/muyue/internal/agent"
|
||||
)
|
||||
|
||||
type HookType string
|
||||
|
||||
const (
|
||||
BeforeToolCall HookType = "before_tool_call"
|
||||
AfterToolCall HookType = "after_tool_call"
|
||||
OnConversationStart HookType = "on_conversation_start"
|
||||
OnToolError HookType = "on_tool_error"
|
||||
)
|
||||
|
||||
type HookFunc func(ctx context.Context, payload HookPayload) error
|
||||
|
||||
type HookPayload struct {
|
||||
ToolName string `json:"tool_name"`
|
||||
Arguments json.RawMessage `json:"arguments,omitempty"`
|
||||
Response *agent.ToolResponse `json:"response,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type Hook struct {
|
||||
Type HookType
|
||||
Plugin string
|
||||
Priority int
|
||||
Fn HookFunc
|
||||
}
|
||||
|
||||
type HookRegistry struct {
|
||||
mu sync.RWMutex
|
||||
hooks map[HookType][]Hook
|
||||
}
|
||||
|
||||
func NewHookRegistry() *HookRegistry {
|
||||
return &HookRegistry{
|
||||
hooks: make(map[HookType][]Hook),
|
||||
}
|
||||
}
|
||||
|
||||
func (hr *HookRegistry) Register(hookType HookType, pluginName string, priority int, fn HookFunc) {
|
||||
hr.mu.Lock()
|
||||
defer hr.mu.Unlock()
|
||||
|
||||
h := Hook{
|
||||
Type: hookType,
|
||||
Plugin: pluginName,
|
||||
Priority: priority,
|
||||
Fn: fn,
|
||||
}
|
||||
hr.hooks[hookType] = append(hr.hooks[hookType], h)
|
||||
|
||||
for i := len(hr.hooks[hookType]) - 1; i > 0; i-- {
|
||||
if hr.hooks[hookType][i].Priority < hr.hooks[hookType][i-1].Priority {
|
||||
hr.hooks[hookType][i], hr.hooks[hookType][i-1] = hr.hooks[hookType][i-1], hr.hooks[hookType][i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (hr *HookRegistry) Fire(ctx context.Context, hookType HookType, payload HookPayload) error {
|
||||
hr.mu.RLock()
|
||||
hooks := make([]Hook, len(hr.hooks[hookType]))
|
||||
copy(hooks, hr.hooks[hookType])
|
||||
hr.mu.RUnlock()
|
||||
|
||||
for _, h := range hooks {
|
||||
if err := h.Fn(ctx, payload); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hr *HookRegistry) RemoveByPlugin(pluginName string) {
|
||||
hr.mu.Lock()
|
||||
defer hr.mu.Unlock()
|
||||
|
||||
for hookType := range hr.hooks {
|
||||
filtered := make([]Hook, 0, len(hr.hooks[hookType]))
|
||||
for _, h := range hr.hooks[hookType] {
|
||||
if h.Plugin != pluginName {
|
||||
filtered = append(filtered, h)
|
||||
}
|
||||
}
|
||||
hr.hooks[hookType] = filtered
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user