sdk: add RegisterInputChannel + NoMemory/Cleaner support

- ChannelDef struct: NoMemory bool + Cleaner func(string) string
- InputChannelRegistrar interface + RegisterInputChannel method
- RegisterOutputChannel now takes ChannelDef parameter
- QQ example registers input channel with NoMemory:true + Cleaner
This commit is contained in:
root
2026-07-29 14:46:15 +08:00
parent c7c66b8d39
commit c5bcae9404
2 changed files with 51 additions and 4 deletions

View File

@ -165,7 +165,28 @@ meta JSON 格式:
"reply_to": 12345 // 可选,回复指定消息 ID "reply_to": 12345 // 可选,回复指定消息 ID
} }
type 枚举: text文字/ voice语音转文字后发送/ image图片URL/ file文件URL`, type 枚举: text文字/ voice语音转文字后发送/ image图片URL/ file文件URL`,
p.handleChannelOutput) sdk.ChannelDef{}, p.handleChannelOutput)
// ---- 注册输入通道(记忆计算层行为) ----
inputCleaner := func(text string) string {
// 从中断模板中提取语义内容:消息来源和发送者昵称
// 模板: 来自「昵称」的私聊/群聊消息(message_id=N)...
// 模板: 【重要!老大消息】来自「昵称」...
cleaned := text
// 去掉模板前缀
if strings.HasPrefix(cleaned, "【重要!老大消息】") {
cleaned = strings.TrimPrefix(cleaned, "【重要!老大消息】")
}
// 提取 "来自「XXX」" 中的昵称作为关键词
if start := strings.Index(cleaned, "来自「"); start >= 0 {
if end := strings.Index(cleaned[start:], "」"); end >= 0 {
nick := cleaned[start+len("来自「") : start+end]
cleaned = nick
}
}
return cleaned
}
s.RegisterInputChannel("qq", sdk.ChannelDef{NoMemory: true, Cleaner: inputCleaner})
// 查询类工具输出清洗器:提取 JSON 中的 content/文本字段参与向量化 // 查询类工具输出清洗器:提取 JSON 中的 content/文本字段参与向量化
cleaner := func(output string) string { cleaner := func(output string) string {

View File

@ -35,6 +35,14 @@ const (
StageAfterOutput Stage = "after_output" StageAfterOutput Stage = "after_output"
) )
// ChannelDef 描述通道在记忆计算层的行为,与 ToolDef.NoMemory/Cleaner 语义一致。
// NoMemory: 此通道输入/输出不参与记忆计算(向量化/关键词提取/蒸馏),但原文保留在上下文中
// Cleaner: 计算层过滤函数,不改原文;仅在向量化/jieba/蒸馏/存档提取关键词时调用
type ChannelDef struct {
NoMemory bool
Cleaner func(string) string
}
// StageContext provides context for stage handlers. // StageContext provides context for stage handlers.
type StageContext struct { type StageContext struct {
mu sync.RWMutex mu sync.RWMutex
@ -156,8 +164,11 @@ type StageRegistrar func(stage Stage, handler StageHandler)
// APIRegistrar registers a plugin API for external access. // APIRegistrar registers a plugin API for external access.
type APIRegistrar func(name string) error type APIRegistrar func(name string) error
// InputChannelRegistrar registers an input channel with its memory behavior.
type InputChannelRegistrar func(name string, def ChannelDef) error
// OutputChannelRegistrar registers an output channel that the output_send tool can use. // OutputChannelRegistrar registers an output channel that the output_send tool can use.
type OutputChannelRegistrar func(name string, caps int, desc string, handler ToolHandler) error type OutputChannelRegistrar func(name string, caps int, desc string, def ChannelDef, handler ToolHandler) error
// Output capability flags // Output capability flags
const ( const (
@ -176,6 +187,7 @@ type PluginSDK struct {
regStage StageRegistrar regStage StageRegistrar
regAPI APIRegistrar regAPI APIRegistrar
regOutput OutputChannelRegistrar regOutput OutputChannelRegistrar
regInput InputChannelRegistrar
io IOInjector io IOInjector
mem MemoryAPI mem MemoryAPI
textMem TextMemoryAPI textMem TextMemoryAPI
@ -289,10 +301,21 @@ func (s *PluginSDK) RegisterPluginAPI(name string) error {
// name: channel name (e.g. "qq", "webui") // name: channel name (e.g. "qq", "webui")
// caps: bitmask of supported output capabilities (CapText, CapFile, etc.) // caps: bitmask of supported output capabilities (CapText, CapFile, etc.)
// desc: description of the channel, expected meta format, and type enum // desc: description of the channel, expected meta format, and type enum
// def: 通道在记忆计算层的行为NoMemory/Cleaner
// handler: receives args map with keys: payload (string), type (string), meta (string|optional) // handler: receives args map with keys: payload (string), type (string), meta (string|optional)
func (s *PluginSDK) RegisterOutputChannel(name string, caps int, desc string, handler ToolHandler) error { func (s *PluginSDK) RegisterOutputChannel(name string, caps int, desc string, def ChannelDef, handler ToolHandler) error {
if s.regOutput != nil { if s.regOutput != nil {
return s.regOutput(name, caps, desc, handler) return s.regOutput(name, caps, desc, def, handler)
}
return nil
}
// RegisterInputChannel registers an input channel with its memory behavior.
// def.NoMemory: 此通道输入不参与记忆计算
// def.Cleaner: 计算层对输入文本清洗后(不改原文)再向量化/提关键词
func (s *PluginSDK) RegisterInputChannel(name string, def ChannelDef) error {
if s.regInput != nil {
return s.regInput(name, def)
} }
return nil return nil
} }
@ -300,6 +323,9 @@ func (s *PluginSDK) RegisterOutputChannel(name string, caps int, desc string, ha
// SetOutputChannelRegistrar sets the output channel registrar (called by the core at startup). // SetOutputChannelRegistrar sets the output channel registrar (called by the core at startup).
func (s *PluginSDK) SetOutputChannelRegistrar(r OutputChannelRegistrar) { s.regOutput = r } func (s *PluginSDK) SetOutputChannelRegistrar(r OutputChannelRegistrar) { s.regOutput = r }
// SetInputChannelRegistrar sets the input channel registrar (called by the core at startup).
func (s *PluginSDK) SetInputChannelRegistrar(r InputChannelRegistrar) { s.regInput = r }
// SetIOInjector sets the IO injector (called by the core at startup). // SetIOInjector sets the IO injector (called by the core at startup).
func (s *PluginSDK) SetIOInjector(io IOInjector) { s.io = io } func (s *PluginSDK) SetIOInjector(io IOInjector) { s.io = io }