mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-25 03:18:08 +00:00
重构: 插件自注册 + .so 动态加载 + 中断打断机制
- 所有内置插件 init() 自注册 (plugin.RegisterFactory), 移除 main.go 硬编码 - 新增 .so 动态加载器 (internal/plugin/dynamic.go), 插件可编译为 plugin.so - 新增 plugin.json 元数据 (internal/plugin/manifest.go) - 新增 interceptLoop 独立 goroutine: (a) cancelLLM() 取消进行中的 HTTP 请求 (b) interceptCh → drainInterrupt() 注入 [打断消息] 到 LLM 上下文 (c) InjectInput 空闲时触发新处理循环 - 新增 internal/plugins/all.go 空白导入触发所有内置插件 init() - internal/sdk/ 作为 PluginSDK 正式 Go API - internal/api/ → internal/plugins/webui/ 迁移 - 删除旧 cmd/cli/, 使用 cmd/waiter/ 替代 - 更新 PLAN.md / ARCHITECTURE.md / README.md 文档
This commit is contained in:
88
internal/plugins/openclaw/plugin.go
Normal file
88
internal/plugins/openclaw/plugin.go
Normal file
@ -0,0 +1,88 @@
|
||||
package openclaw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gitcode.com/JianFeeeee/HomeAgent/internal/plugin"
|
||||
sdk "gitcode.com/JianFeeeee/HomeAgent/internal/sdk"
|
||||
)
|
||||
|
||||
// SkillsDir 由 main.go 在 Load() 前设置,指向 SKILL.md 存放目录。
|
||||
var SkillsDir string
|
||||
|
||||
func init() {
|
||||
plugin.RegisterFactory("openclaw", func(name string, config map[string]interface{}) (sdk.Plugin, error) {
|
||||
dir := SkillsDir
|
||||
if dir == "" {
|
||||
dir = filepath.Join(config["data_dir"].(string), "skills")
|
||||
}
|
||||
return New(name, dir), nil
|
||||
})
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
name string
|
||||
skillsDir string
|
||||
skills []*plugin.SKILLPlugin
|
||||
}
|
||||
|
||||
func New(name, skillsDir string) *Plugin {
|
||||
return &Plugin{
|
||||
name: name,
|
||||
skillsDir: skillsDir,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Plugin) Name() string { return p.name }
|
||||
|
||||
func (p *Plugin) Start(s *sdk.PluginSDK) error {
|
||||
entries, err := os.ReadDir(p.skillsDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("read skills dir %s: %w", p.skillsDir, err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
skillPath := filepath.Join(p.skillsDir, entry.Name())
|
||||
sk, err := plugin.LoadSKILL(skillPath)
|
||||
if err != nil {
|
||||
log.Printf("[openclaw] load skill %s: %v", entry.Name(), err)
|
||||
continue
|
||||
}
|
||||
p.skills = append(p.skills, sk)
|
||||
|
||||
// Register each tool defined in the SKILL
|
||||
for _, td := range sk.Tools() {
|
||||
name := td.Name
|
||||
def := sdk.ToolDef{
|
||||
Name: name,
|
||||
Description: td.Description,
|
||||
Parameters: td.Parameters,
|
||||
}
|
||||
// SKILL tools are informational (advisory) — no handler
|
||||
if err := s.RegisterTool(name, def, nil); err != nil {
|
||||
log.Printf("[openclaw] register tool %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Register IO config as a channel if defined
|
||||
if iocfg := sk.IOConfig(); iocfg != nil {
|
||||
log.Printf("[openclaw] skill %s io: type=%s in=%s out=%s caps=%v",
|
||||
sk.Name(), iocfg.Type, iocfg.InputRoute, iocfg.OutputRoute, iocfg.OutputCaps)
|
||||
}
|
||||
|
||||
log.Printf("[openclaw] loaded skill: %s v%s", sk.Name(), sk.Version())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) Stop() error {
|
||||
p.skills = nil
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user