mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-04 00:03:59 +00:00
feat(shm): Cleaner 迁移到 SharedRef(§13.4)
- CleanerInvokeParams/Result 的 Text 改为 TextRef SharedRef - cleanerProxy: 写 text 到 arena,传 SharedRef,读结果 SharedRef - 插件侧 cleaner.invoke: 从 SharedRef 读 input,清洗后写回 arena 返回 TextRef - NewHost(): 分配空间含 arena(256KB)
This commit is contained in:
@ -34,7 +34,7 @@ type coreHandler struct {
|
|||||||
// invokeTool/invokeCleaner/invokeStageFn/invokeOutput 反向调用插件(内核 → 插件)。
|
// invokeTool/invokeCleaner/invokeStageFn/invokeOutput 反向调用插件(内核 → 插件)。
|
||||||
// 由 Plugin 注入,注册回调时用它们构造 handler。
|
// 由 Plugin 注入,注册回调时用它们构造 handler。
|
||||||
invokeTool func(name string, args map[string]interface{}) (interface{}, error)
|
invokeTool func(name string, args map[string]interface{}) (interface{}, error)
|
||||||
invokeCleaner func(scope, name, text string) (string, error)
|
invokeCleaner func(scope, name string, textRef SharedRef) (SharedRef, error)
|
||||||
invokeStageFn func(ctx context.Context, stage string, seq uint64) error
|
invokeStageFn func(ctx context.Context, stage string, seq uint64) error
|
||||||
invokeOutput func(channel string, args map[string]interface{}) (interface{}, error)
|
invokeOutput func(channel string, args map[string]interface{}) (interface{}, error)
|
||||||
|
|
||||||
@ -600,11 +600,16 @@ func (h *coreHandler) cleanerProxy(scope, name string, enabled bool) (func(strin
|
|||||||
return nil, fmt.Errorf("%s %s 声明 Cleaner,但清洗回调通道未就绪", scope, name)
|
return nil, fmt.Errorf("%s %s 声明 Cleaner,但清洗回调通道未就绪", scope, name)
|
||||||
}
|
}
|
||||||
return func(text string) string {
|
return func(text string) string {
|
||||||
cleaned, err := h.invokeCleaner(scope, name, text)
|
ref, err := h.host.unified.arenaWrite([]byte(text))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
return cleaned
|
resultRef, err := h.invokeCleaner(scope, name, ref)
|
||||||
|
if err != nil {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
result := h.host.unified.arenaRead(resultRef)
|
||||||
|
return string(result)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -222,23 +222,23 @@ func (p *Plugin) invokeTool(name string, args map[string]interface{}) (interface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// invokeCleaner 在插件进程内执行工具或通道注册时提供的 Cleaner 函数。
|
// invokeCleaner 在插件进程内执行工具或通道注册时提供的 Cleaner 函数。
|
||||||
func (p *Plugin) invokeCleaner(scope, name, text string) (string, error) {
|
func (p *Plugin) invokeCleaner(scope, name string, textRef SharedRef) (SharedRef, error) {
|
||||||
if p.proc == nil {
|
if p.proc == nil {
|
||||||
return "", ErrProcessExited
|
return SharedRef{}, ErrProcessExited
|
||||||
}
|
}
|
||||||
raw, err := p.proc.Call(MethodCleanerInvoke, CleanerInvokeParams{
|
raw, err := p.proc.Call(MethodCleanerInvoke, CleanerInvokeParams{
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
Name: name,
|
Name: name,
|
||||||
Text: text,
|
TextRef: textRef,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return SharedRef{}, err
|
||||||
}
|
}
|
||||||
var res CleanerInvokeResult
|
var res CleanerInvokeResult
|
||||||
if err := json.Unmarshal(raw, &res); err != nil {
|
if err := json.Unmarshal(raw, &res); err != nil {
|
||||||
return "", fmt.Errorf("proc: %s %s Cleaner %s 应答解析失败: %w", p.name, scope, name, err)
|
return SharedRef{}, fmt.Errorf("proc: %s %s Cleaner %s 应答解析失败: %w", p.name, scope, name, err)
|
||||||
}
|
}
|
||||||
return res.Text, nil
|
return res.TextRef, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Plugin) invokeStage(ctx context.Context, stage string, seq uint64) error {
|
func (p *Plugin) invokeStage(ctx context.Context, stage string, seq uint64) error {
|
||||||
|
|||||||
@ -213,14 +213,15 @@ type ToolInvokeResult struct {
|
|||||||
|
|
||||||
// CleanerInvokeParams / CleanerInvokeResult:跨进程计算层清洗。
|
// CleanerInvokeParams / CleanerInvokeResult:跨进程计算层清洗。
|
||||||
// Scope 取 tool / input / output,Name 是工具名或通道名。
|
// Scope 取 tool / input / output,Name 是工具名或通道名。
|
||||||
|
// TextRef 指向共享内存 arena 中的实际文本数据。
|
||||||
type CleanerInvokeParams struct {
|
type CleanerInvokeParams struct {
|
||||||
Scope string `json:"scope"`
|
Scope string `json:"scope"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Text string `json:"text"`
|
TextRef SharedRef `json:"text_ref"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CleanerInvokeResult struct {
|
type CleanerInvokeResult struct {
|
||||||
Text string `json:"text"`
|
TextRef SharedRef `json:"text_ref"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
30
internal/plugin/proc/testdata/stageplugin.go
vendored
30
internal/plugin/proc/testdata/stageplugin.go
vendored
@ -40,6 +40,9 @@ var (
|
|||||||
|
|
||||||
shm []byte
|
shm []byte
|
||||||
shmSize int
|
shmSize int
|
||||||
|
region []byte // 完整统一区域 mmap
|
||||||
|
arenaOff uint32
|
||||||
|
arenaUsed uint32
|
||||||
)
|
)
|
||||||
|
|
||||||
func send(v interface{}) {
|
func send(v interface{}) {
|
||||||
@ -233,6 +236,8 @@ func main() {
|
|||||||
// 统一区域:前 64B 是 SuperBlock,StageContext 段在其后
|
// 统一区域:前 64B 是 SuperBlock,StageContext 段在其后
|
||||||
ctxOff := binary.LittleEndian.Uint32(m[20:])
|
ctxOff := binary.LittleEndian.Uint32(m[20:])
|
||||||
ctxSize := binary.LittleEndian.Uint32(m[24:])
|
ctxSize := binary.LittleEndian.Uint32(m[24:])
|
||||||
|
region = m
|
||||||
|
arenaOff = binary.LittleEndian.Uint32(m[36:])
|
||||||
shm = m[ctxOff : ctxOff+ctxSize]
|
shm = m[ctxOff : ctxOff+ctxSize]
|
||||||
}
|
}
|
||||||
send(response{ID: req.ID, Result: map[string]interface{}{
|
send(response{ID: req.ID, Result: map[string]interface{}{
|
||||||
@ -282,9 +287,12 @@ func main() {
|
|||||||
|
|
||||||
case "cleaner.invoke":
|
case "cleaner.invoke":
|
||||||
var p struct {
|
var p struct {
|
||||||
Scope string `json:"scope"`
|
Scope string `json:"scope"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Text string `json:"text"`
|
TextRef struct {
|
||||||
|
Offset uint32 `json:"offset"`
|
||||||
|
Length uint32 `json:"length"`
|
||||||
|
} `json:"text_ref"`
|
||||||
}
|
}
|
||||||
json.Unmarshal(req.Params, &p)
|
json.Unmarshal(req.Params, &p)
|
||||||
valid := (p.Scope == "tool" && p.Name == "demo_upper") ||
|
valid := (p.Scope == "tool" && p.Name == "demo_upper") ||
|
||||||
@ -294,8 +302,22 @@ func main() {
|
|||||||
send(response{ID: req.ID, Error: "未注册 Cleaner"})
|
send(response{ID: req.ID, Error: "未注册 Cleaner"})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// 从 arena 读文本
|
||||||
|
input := string(region[p.TextRef.Offset : p.TextRef.Offset+p.TextRef.Length])
|
||||||
|
output := p.Scope + "-cleaned:" + input
|
||||||
|
// 写回 arena
|
||||||
|
off := arenaUsed
|
||||||
|
if off == 0 {
|
||||||
|
off = 1
|
||||||
|
}
|
||||||
|
end := off + uint32(len(output))
|
||||||
|
copy(region[arenaOff+end-uint32(len(output)):arenaOff+end], output)
|
||||||
|
arenaUsed = end
|
||||||
send(response{ID: req.ID, Result: map[string]interface{}{
|
send(response{ID: req.ID, Result: map[string]interface{}{
|
||||||
"text": p.Scope + "-cleaned:" + p.Text,
|
"text_ref": map[string]interface{}{
|
||||||
|
"offset": arenaOff + off,
|
||||||
|
"length": uint32(len(output)),
|
||||||
|
},
|
||||||
}})
|
}})
|
||||||
|
|
||||||
case "stage.invoke":
|
case "stage.invoke":
|
||||||
|
|||||||
Reference in New Issue
Block a user