From 3cad4b635f21b93d8b4d190b42b0c7bc6614bcfd Mon Sep 17 00:00:00 2001 From: root Date: Fri, 17 Jul 2026 11:25:54 +0800 Subject: [PATCH] RegisterStage: add scope parameter, remove RegisterStageOwnTools - SDK: RegisterStage(stage, handler, scope...) with StageScopeGlobal/StageScopeOwnTools - Delete RegisterStageOwnTools, migrate cmd and qq plugins - Internal SDK: add StageScope alias - Docs: update all zh/en docs for C ABI buildmode and stage scope - C ABI: fix nil errorOut in Handle.Start/Handle.Stop (SIGSEGV fix) - C ABI header: add dispatch IDs 26-45 for Settings/Doc/Knowledge/LLM/Social/TextMemory --- docs/en/ARCHITECTURE.md | 6 +- docs/en/OVERVIEW.md | 2 +- docs/en/PLUGIN_DEV.md | 24 ++++--- docs/zh/ARCHITECTURE.md | 6 +- docs/zh/OVERVIEW.md | 2 +- docs/zh/PLUGIN_DEV.md | 12 ++-- internal/plugin/cabi/loader.go | 118 +++++++++++++++++++++++++-------- internal/plugin/cabi/types.go | 70 ++++++++++++------- internal/plugins/cmd/plugin.go | 4 +- internal/sdk/plugin.go | 6 ++ 10 files changed, 173 insertions(+), 77 deletions(-) diff --git a/docs/en/ARCHITECTURE.md b/docs/en/ARCHITECTURE.md index 7ec870b..0b53cfc 100644 --- a/docs/en/ARCHITECTURE.md +++ b/docs/en/ARCHITECTURE.md @@ -239,7 +239,7 @@ VM built-ins: `json.encode` / `json.decode` / `log` / `http_get` / `http_post`. | Method | Registration Mechanism | Compilation | Usage | |--------|----------------------|-------------|-------| | Built-in | `init()` → `RegisterFactory` | `internal/plugins/` compiled into kernel | webui/cli/timer/mcp etc. | -| External `.so`/`.dll` | `plugin.Open` dynamic loading | `-buildmode=plugin` | qq/files/web/memo etc. | +| External `.so` | C ABI dynamic loading | `-buildmode=c-shared` + bridge | qq/files/web/memo etc. | | Lua script plugin | Parse `main.lua` to register tools | No compilation, hot-reload | luaplugintest/testlua etc. | | SKILL plugin | Parse `SKILL.md` | Markdown definition | OpenClaw compatible | @@ -253,7 +253,7 @@ Lua script plugin loading: `internal/lua/` → parse `main.lua` via Lua VM, call Plugin ──→ Kernel RegisterTool(name, fn) ──→ buildToolDefs() / executeToolCall() -RegisterStage(stage, fn) ──→ runStage() called at corresponding phase +RegisterStage(stage, fn, scope...) ──→ runStage() called at corresponding phase (scope: global / own-tools-only) Subscribe(event, fn) ──→ Publish() notify all subscribers RegisterOutputChannel(name, caps, desc, handler) ──→ output_send__{name} tool generation ``` @@ -262,7 +262,7 @@ RegisterOutputChannel(name, caps, desc, handler) ──→ output_send__{name} t ```go sdk.RegisterTool(name, def, handler) -sdk.RegisterStage(stage, handler) +sdk.RegisterStage(stage, handler, scope...) sdk.Publish(event) sdk.InjectInput(source, channel, payload) sdk.InjectInterrupt(source, channel, payload) diff --git a/docs/en/OVERVIEW.md b/docs/en/OVERVIEW.md index c9a2599..ef759c3 100644 --- a/docs/en/OVERVIEW.md +++ b/docs/en/OVERVIEW.md @@ -49,7 +49,7 @@ Code is in the project root, implemented in Go. **Plugin System** (`internal/plugin/`): - Built-in plugins: Go `init()` self-registration, compiled into kernel -- External plugins: Go `-buildmode=plugin` compiled to `.so`/`.dll`, dynamically loaded via `plugin.Open`; also supports Lua script plugins +- External plugins: Go `-buildmode=c-shared` compiled to `.so`, dynamically loaded via C ABI bridge; also supports Lua script plugins - PluginSDK (`internal/sdk/`) defines four channels: RegisterTool / RegisterStage / Subscribe / RegisterOutputChannel - 7 stage hooks: on_input → pre_action → post_action → before_toolcall → after_toolcall → before_output → after_output diff --git a/docs/en/PLUGIN_DEV.md b/docs/en/PLUGIN_DEV.md index 4780db3..1d6b370 100644 --- a/docs/en/PLUGIN_DEV.md +++ b/docs/en/PLUGIN_DEV.md @@ -105,7 +105,7 @@ plugindev build Execution process: 1. Reads `plg.json` to determine target platform -2. **Go plugin**: Runs `go build -buildmode=plugin` (Linux) or `-buildmode=c-shared` (Windows) +2. **Go plugin**: Runs `go build -buildmode=c-shared` (produces `.so` + C ABI header) 3. **Lua plugin**: Packages source code directly, no compilation needed 4. Generates `plugin.json` manifest file 5. Packages as `.hmap` distribution (zip format, containing `plugin.json` + `plugin.so`/`plugin.dll`/`main.lua`) @@ -181,7 +181,7 @@ func NewPlugin(name string, config map[string]interface{}) (sdk.Plugin, error) { } ``` -For Windows `-buildmode=c-shared`, `plugindev build` auto-generates C ABI bridge code, no manual handling needed. +For `-buildmode=c-shared`, `plugindev build` auto-generates C ABI bridge code (`z_bridge_gen.go` + `z_entry.c`), no manual handling needed. ### PluginSDK Core API @@ -222,19 +222,23 @@ s.RegisterTool("weather_query", sdk.ToolDef{ | `post_action` | LLM returned results | Modify output/tool list | | `before_toolcall` | Before tool execution | Audit, reject, modify params | | `after_toolcall` | After tool execution | Desensitize, rewrite results | -| `before_output` | Before output | Format adaptation | +| `before_output` | Before output | Format adaptation, leak cleanup | | `after_output` | After output | Statistics/logging | ```go +// Global: receive all stage events s.RegisterStage(sdk.StagePreAction, func(ctx *sdk.StageContext) error { - ctx.Lock() - ctx.ContextMsgs = append(ctx.ContextMsgs, map[string]interface{}{ - "role": "system", - "content": "Injected context content", - }) - ctx.Unlock() - return nil + ctx.Lock() + ctx.ContextMsgs = append(ctx.ContextMsgs, map[string]interface{}{ + "role": "system", + "content": "Injected context content", + }) + ctx.Unlock() + return nil }) + +// Own tools only: only before_toolcall/after_toolcall for this plugin's tools +s.RegisterStage(sdk.StageBeforeToolcall, myHandler, sdk.StageScopeOwnTools) ``` #### Configuration Management diff --git a/docs/zh/ARCHITECTURE.md b/docs/zh/ARCHITECTURE.md index eac775c..40dd4d0 100644 --- a/docs/zh/ARCHITECTURE.md +++ b/docs/zh/ARCHITECTURE.md @@ -239,7 +239,7 @@ VM 内置 `json.encode` / `json.decode` / `log` / `http_get` / `http_post`。 | 方式 | 注册机制 | 编译 | 用途 | |------|----------|------|------| | 内置插件 | `init()` → `RegisterFactory` | `internal/plugins/` 编译进内核 | webui/cli/timer/mcp 等 | -| 外部 `.so`/`.dll` | `plugin.Open` 动态加载 | `-buildmode=plugin` | qq/files/web/memo 等 | +| 外部 `.so` | C ABI 动态加载 | `-buildmode=c-shared` + bridge | qq/files/web/memo 等 | | Lua 脚本插件 | 解析 `main.lua` 注册工具 | 无需编译,热加载 | luaplugintest/testlua 等 | | SKILL 插件 | 解析 `SKILL.md` | Markdown 定义 | OpenClaw 兼容 | @@ -253,7 +253,7 @@ Lua 脚本插件加载:`internal/lua/` → 通过 Lua VM 解析 `main.lua`, 插件 ──→ 核心 RegisterTool(name, fn) ──→ buildToolDefs() / executeToolCall() -RegisterStage(stage, fn) ──→ runStage() 在对应阶段调用 +RegisterStage(stage, fn, scope...) ──→ runStage() 在对应阶段调用(scope 控制全局/仅自己工具) Subscribe(event, fn) ──→ Publish() 通知所有订阅者 RegisterOutputChannel(name, caps, desc, handler) ──→ output_send__{name} 工具生成 ``` @@ -262,7 +262,7 @@ RegisterOutputChannel(name, caps, desc, handler) ──→ output_send__{name} ```go sdk.RegisterTool(name, def, handler) -sdk.RegisterStage(stage, handler) +sdk.RegisterStage(stage, handler, scope...) sdk.Publish(event) sdk.InjectInput(source, channel, payload) sdk.InjectInterrupt(source, channel, payload) diff --git a/docs/zh/OVERVIEW.md b/docs/zh/OVERVIEW.md index c2fab68..149811e 100644 --- a/docs/zh/OVERVIEW.md +++ b/docs/zh/OVERVIEW.md @@ -49,7 +49,7 @@ HomeAgent 是一个持续运行的个人智能 Agent 框架。 **插件系统** (`internal/plugin/`): - 内置插件:Go `init()` 自注册,编译进内核 -- 外部插件:Go `-buildmode=plugin` 编译为 `.so`/`.dll`,通过 `plugin.Open` 动态加载;也支持 Lua 脚本插件 +- 外部插件:Go `-buildmode=c-shared` 编译为 `.so`,通过 C ABI bridge 动态加载;也支持 Lua 脚本插件 - PluginSDK (`internal/sdk/`) 定义四通道:RegisterTool / RegisterStage / Subscribe / RegisterOutputChannel - 阶段钩子 7 个:on_input → pre_action → post_action → before_toolcall → after_toolcall → before_output → after_output diff --git a/docs/zh/PLUGIN_DEV.md b/docs/zh/PLUGIN_DEV.md index ee87807..2a07072 100644 --- a/docs/zh/PLUGIN_DEV.md +++ b/docs/zh/PLUGIN_DEV.md @@ -106,10 +106,10 @@ plugindev build 执行过程: 1. 读取 `plg.json` 确定目标平台 -2. **Go 插件**:执行 `go build -buildmode=plugin`(Linux)或 `-buildmode=c-shared`(Windows) +2. **Go 插件**:执行 `go build -buildmode=c-shared`(生成 `.so` + C ABI header) 3. **Lua 插件**:直接打包源码,无需编译 4. 生成 `plugin.json` 清单文件 -5. 打包为 `.hmap` 分发包(zip 格式,内含 `plugin.json` + `plugin.so`/`plugin.dll`/`main.lua`) +5. 打包为 `.hmap` 分发包(zip 格式,内含 `plugin.json` + `plugin.so` + `plugin.h` + `main.lua`) 输出在 `dist/` 目录: ``` @@ -182,7 +182,7 @@ func NewPlugin(name string, config map[string]interface{}) (sdk.Plugin, error) { } ``` -对于 Windows `-buildmode=c-shared`,`plugindev build` 自动生成 C ABI bridge 代码,无需手动处理。 +对于 `-buildmode=c-shared`,`plugindev build` 自动生成 C ABI bridge 代码(`z_bridge_gen.go` + `z_entry.c`),无需手动处理。 ### PluginSDK 核心 API @@ -223,10 +223,11 @@ s.RegisterTool("weather_query", sdk.ToolDef{ | `post_action` | LLM 返回结果 | 修改输出/工具列表 | | `before_toolcall` | 工具调用前 | 审计、拒绝、改参 | | `after_toolcall` | 工具执行后 | 脱敏、改写结果 | -| `before_output` | 输出前 | 格式适配 | +| `before_output` | 输出前 | 格式适配、泄漏清洗 | | `after_output` | 输出后 | 统计日志 | ```go +// 全局监听:所有插件的阶段事件 s.RegisterStage(sdk.StagePreAction, func(ctx *sdk.StageContext) error { ctx.Lock() ctx.ContextMsgs = append(ctx.ContextMsgs, map[string]interface{}{ @@ -236,6 +237,9 @@ s.RegisterStage(sdk.StagePreAction, func(ctx *sdk.StageContext) error { ctx.Unlock() return nil }) + +// 仅自己工具:仅监听自己注册的 tool 的 before_toolcall/after_toolcall +s.RegisterStage(sdk.StageBeforeToolcall, myHandler, sdk.StageScopeOwnTools) ``` #### 配置管理 diff --git a/internal/plugin/cabi/loader.go b/internal/plugin/cabi/loader.go index a89c5e3..cfc82f3 100644 --- a/internal/plugin/cabi/loader.go +++ b/internal/plugin/cabi/loader.go @@ -44,6 +44,7 @@ import "C" import ( "encoding/json" "fmt" + "log" "sync" "sync/atomic" "unsafe" @@ -142,16 +143,22 @@ func (h *Handle) FreeCoreAPI() { // Start calls the plugin's Start with a CoreAPI pointer. func (h *Handle) Start(corePtr unsafe.Pointer) error { - if ret := int(C.call_start_plugin(h.api, corePtr, C.int(1), nil)); ret != 0 { - return fmt.Errorf("start_plugin failed") + var cErr *C.char + if ret := int(C.call_start_plugin(h.api, corePtr, C.int(1), &cErr)); ret != 0 { + errMsg := "" + if cErr != nil { errMsg = C.GoString(cErr); C.api_free_string(h.api, cErr) } + return fmt.Errorf("start_plugin: %s", errMsg) } return nil } // Stop calls the plugin's Stop. func (h *Handle) Stop() error { - if ret := int(C.call_stop_plugin(h.api, nil)); ret != 0 { - return fmt.Errorf("stop_plugin failed") + var cErr *C.char + if ret := int(C.call_stop_plugin(h.api, &cErr)); ret != 0 { + errMsg := "" + if cErr != nil { errMsg = C.GoString(cErr); C.api_free_string(h.api, cErr) } + return fmt.Errorf("stop_plugin: %s", errMsg) } return nil } @@ -214,10 +221,13 @@ func pluginInvokeOutput(pluginID int32, channel, payload string) error { if ps.api == nil { return fmt.Errorf("plugin %d: nil api", pluginID) } cCh := C.CString(channel) cPayload := C.CString(payload) + var cErr *C.char defer C.free(unsafe.Pointer(cCh)) defer C.free(unsafe.Pointer(cPayload)) - if ret := int(C.call_invoke_output(ps.api, cCh, nil, cPayload, nil)); ret != 0 { - return fmt.Errorf("invoke_output %s failed", channel) + if ret := int(C.call_invoke_output(ps.api, cCh, nil, cPayload, &cErr)); ret != 0 { + errMsg := "" + if cErr != nil { errMsg = C.GoString(cErr); C.api_free_string(ps.api, cErr) } + return fmt.Errorf("invoke_output %s: %s", channel, errMsg) } return nil } @@ -229,10 +239,13 @@ func pluginInvokeStage(pluginID int32, stage, ctxJSON string) error { if ps.api == nil { return fmt.Errorf("plugin %d: nil api", pluginID) } cStage := C.CString(stage) cCtx := C.CString(ctxJSON) + var cErr *C.char defer C.free(unsafe.Pointer(cStage)) defer C.free(unsafe.Pointer(cCtx)) - if ret := int(C.call_invoke_stage(ps.api, cStage, cCtx, nil)); ret != 0 { - return fmt.Errorf("invoke_stage %s failed", stage) + if ret := int(C.call_invoke_stage(ps.api, cStage, cCtx, &cErr)); ret != 0 { + errMsg := "" + if cErr != nil { errMsg = C.GoString(cErr); C.api_free_string(ps.api, cErr) } + return fmt.Errorf("invoke_stage %s: %s", stage, errMsg) } return nil } @@ -294,8 +307,18 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 pid := pluginID chName := a1 s.RegisterOutputChannel(chName, n1, a2, func(args map[string]interface{}) (interface{}, error) { - argsJSON, _ := json.Marshal(args) - return nil, pluginInvokeOutput(pid, chName, string(argsJSON)) + // Output is async: return immediately, send in background + // to avoid nested cgo calls (cgo within cgo can crash) + go func() { + argsJSON, _ := json.Marshal(args) + log.Printf("[dispatch] async output %s/%s args=%s", ps.name, chName, string(argsJSON)) + if err := pluginInvokeOutput(pid, chName, string(argsJSON)); err != nil { + log.Printf("[dispatch] async output %s/%s failed: %v", ps.name, chName, err) + } else { + log.Printf("[dispatch] async output %s/%s OK", ps.name, chName) + } + }() + return map[string]interface{}{"status": "queued"}, nil }) return 0 @@ -324,7 +347,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 entities, relations, err := mem.Recall([]string{a1}, n1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(map[string]interface{}{"entities": entities, "relations": relations}) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -341,7 +364,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 r, err := mem.Introspect() if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(r) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -364,7 +387,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 case 14: // CORE_DOC_QUERY if dm := s.DocMemory(); dm != nil { b, _ := json.Marshal(dm.Query(a1, n1)) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -373,7 +396,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 results, err := kn.Search(a1, n1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(results) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -382,7 +405,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 v, err := sett.Get(a1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(v) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -405,7 +428,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 case 19: // CORE_LLM_LIST_SOURCES if llm := s.LLM(); llm != nil { b, _ := json.Marshal(llm.ListSources()) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -420,7 +443,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 p, err := social.GetPerson(a1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(p) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -429,7 +452,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 profiles, err := social.GetNetwork(a1, n1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(profiles) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -450,7 +473,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 v, err := sett.GetCore(a1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(v) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -467,7 +490,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 keys, err := sett.ListCore(a1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(keys) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -476,7 +499,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 v, err := sett.GetPlugin(a1, a2) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(v) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -493,7 +516,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 keys, err := sett.ListPlugin(a1, a2) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(keys) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -514,7 +537,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 case 34: // CORE_DOC_STATS if dm := s.DocMemory(); dm != nil { b, _ := json.Marshal(dm.Stats()) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -529,14 +552,14 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 list, err := kn.List() if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(list) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 case 37: // CORE_LLM_CURRENT_SOURCE if llm := s.LLM(); llm != nil { b, _ := json.Marshal(llm.CurrentSource()) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -544,7 +567,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 if social := s.Social(); social != nil { val, ok := social.GetTrait(a1, a2) b, _ := json.Marshal(map[string]interface{}{"value": val, "found": ok}) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -553,7 +576,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 rels, err := social.GetRelations(a1) if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(rels) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -562,7 +585,7 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 persons, err := social.ListPersons() if err != nil { setErr(errorOut, err); return 1 } b, _ := json.Marshal(persons) - *result = C.CString(string(b)) + setResult(result, string(b)) } return 0 @@ -573,6 +596,39 @@ func go_core_dispatch(methodID C.int, ctx unsafe.Pointer, s1, s2, s3 *C.char, i1 if err := tm.Append(evt); err != nil { setErr(errorOut, err); return 1 } } return 0 + + case 42: // CORE_SETTINGS_LIST + if sett := s.Settings(); sett != nil { + keys, err := sett.List(a1) + if err != nil { setErr(errorOut, err); return 1 } + b, _ := json.Marshal(keys) + setResult(result, string(b)) + } + return 0 + + case 43: // CORE_SETTINGS_DEFS + if sett := s.Settings(); sett != nil { + defs := sett.Defs(a1) + b, _ := json.Marshal(defs) + setResult(result, string(b)) + } + return 0 + + case 44: // CORE_SETTINGS_DUMP + if sett := s.Settings(); sett != nil { + dump := sett.Dump() + b, _ := json.Marshal(dump) + setResult(result, string(b)) + } + return 0 + + case 45: // CORE_SETTINGS_PLUGINS + if sett := s.Settings(); sett != nil { + plugins := sett.Plugins() + b, _ := json.Marshal(plugins) + setResult(result, string(b)) + } + return 0 } return 0 } @@ -587,3 +643,9 @@ func setErr(errOut **C.char, err error) { *errOut = C.CString(err.Error()) } } + +func setResult(result **C.char, v string) { + if result != nil { + *result = C.CString(v) + } +} diff --git a/internal/plugin/cabi/types.go b/internal/plugin/cabi/types.go index 70cd229..c734a57 100644 --- a/internal/plugin/cabi/types.go +++ b/internal/plugin/cabi/types.go @@ -8,29 +8,49 @@ const ( // Dispatch method IDs (mirrors the plugin side constants) const ( - CoreRegisterTool = 1 - CoreRegisterStage = 2 - CoreRegisterOutputCh = 3 - CoreRegisterPluginAPI = 4 - CoreInjectText = 5 - CoreInjectInterruptText = 6 - CoreInjectTextNoMemory = 7 - CoreSetAutoRestart = 8 - CoreMemoryRecall = 9 - CoreMemoryCommit = 10 - CoreMemoryIntrospect = 11 - CoreMemoryMerge = 12 - CoreMemoryPurge = 13 - CoreDocQuery = 14 - CoreKnowledgeSearch = 15 - CoreSettingsGet = 16 - CoreSettingsSet = 17 - CoreSettingsRegisterDef = 18 - CoreLLMListSources = 19 - CoreLLMSetSource = 20 - CoreSocialGetPerson = 21 - CoreSocialGetNetwork = 22 - CoreSubscribe = 23 - CoreUnsubscribe = 24 - CoreFreeString = 25 + CoreRegisterTool = 1 + CoreRegisterStage = 2 + CoreRegisterOutputCh = 3 + CoreRegisterPluginAPI = 4 + CoreInjectText = 5 + CoreInjectInterruptText = 6 + CoreInjectTextNoMemory = 7 + CoreSetAutoRestart = 8 + CoreMemoryRecall = 9 + CoreMemoryCommit = 10 + CoreMemoryIntrospect = 11 + CoreMemoryMerge = 12 + CoreMemoryPurge = 13 + CoreDocQuery = 14 + CoreKnowledgeSearch = 15 + CoreSettingsGet = 16 + CoreSettingsSet = 17 + CoreSettingsRegisterDef = 18 + CoreLLMListSources = 19 + CoreLLMSetSource = 20 + CoreSocialGetPerson = 21 + CoreSocialGetNetwork = 22 + CoreSubscribe = 23 + CoreUnsubscribe = 24 + CoreFreeString = 25 + CoreSettingsGetCore = 26 + CoreSettingsSetCore = 27 + CoreSettingsListCore = 28 + CoreSettingsGetPlugin = 29 + CoreSettingsSetPlugin = 30 + CoreSettingsListPlugin = 31 + CoreDocInsert = 32 + CoreDocRemove = 33 + CoreDocStats = 34 + CoreKnowledgeAdd = 35 + CoreKnowledgeList = 36 + CoreLLMCurrentSource = 37 + CoreSocialGetTrait = 38 + CoreSocialGetRelations = 39 + CoreSocialListPersons = 40 + CoreTextMemoryAppend = 41 + CoreSettingsList = 42 + CoreSettingsDefs = 43 + CoreSettingsDump = 44 + CoreSettingsPlugins = 45 ) diff --git a/internal/plugins/cmd/plugin.go b/internal/plugins/cmd/plugin.go index 4e749b0..51c5fe5 100644 --- a/internal/plugins/cmd/plugin.go +++ b/internal/plugins/cmd/plugin.go @@ -214,7 +214,7 @@ func (p *Plugin) Start(s *sdk.PluginSDK) error { }, nil }) - s.RegisterStageOwnTools(sdk.StageBeforeToolcall, func(ctx *sdk.StageContext) error { + s.RegisterStage(sdk.StageBeforeToolcall, func(ctx *sdk.StageContext) error { if len(ctx.ToolCalls) == 0 { return nil } @@ -233,7 +233,7 @@ func (p *Plugin) Start(s *sdk.PluginSDK) error { return nil } return nil - }) + }, sdk.StageScopeOwnTools) return nil } diff --git a/internal/sdk/plugin.go b/internal/sdk/plugin.go index d92f100..e61543d 100644 --- a/internal/sdk/plugin.go +++ b/internal/sdk/plugin.go @@ -37,6 +37,12 @@ type ToolDef = pubsdk.ToolDef type IOInjector = pubsdk.IOInjector type ToolRegistrar = pubsdk.ToolRegistrar type StageRegistrar = pubsdk.StageRegistrar +type StageScope = pubsdk.StageScope + +const ( + StageScopeGlobal = pubsdk.StageScopeGlobal + StageScopeOwnTools = pubsdk.StageScopeOwnTools +) type APIRegistrar = pubsdk.APIRegistrar type OutputChannelRegistrar = pubsdk.OutputChannelRegistrar