mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-09-20 00:48:12 +00:00
feat(shm): Cleaner SharedRef + ContextPolicy (§13.4/§13.8)
- cleaner.invoke 协议: TextRef SharedRef 替代内联 text - 插件侧 arenaWrite/SharedRef 读写辅助 - ToolDef.ContextPolicy 字段(默认 none / 可设 prune) - 握手解析统一区域 SuperBlock + arena 元数据
This commit is contained in:
@ -42,6 +42,9 @@ const (
|
|||||||
sbOffCtxSize = 24
|
sbOffCtxSize = 24
|
||||||
sbOffEvtOff = 28
|
sbOffEvtOff = 28
|
||||||
sbOffEvtSize = 32
|
sbOffEvtSize = 32
|
||||||
|
sbOffArenaOff = 36
|
||||||
|
sbOffArenaCap = 40
|
||||||
|
sbOffArenaUsed = 44
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---- StageContext 段内部布局(与内核 internal/plugin/proc/shm.go 一致)----
|
// ---- StageContext 段内部布局(与内核 internal/plugin/proc/shm.go 一致)----
|
||||||
@ -89,6 +92,43 @@ const (
|
|||||||
flagResponseSet = 1
|
flagResponseSet = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SharedRef 跨进程共享内存描述符。
|
||||||
|
type SharedRef struct {
|
||||||
|
Offset uint32 `json:"offset"`
|
||||||
|
Length uint32 `json:"length"`
|
||||||
|
Generation uint32 `json:"generation"`
|
||||||
|
Flags uint32 `json:"flags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SharedRef) IsZero() bool { return r.Offset == 0 && r.Length == 0 }
|
||||||
|
func (r SharedRef) Slice(data []byte) []byte {
|
||||||
|
if r.IsZero() || int(r.Offset)+int(r.Length) > len(data) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return data[r.Offset : r.Offset+r.Length]
|
||||||
|
}
|
||||||
|
|
||||||
|
// arena 辅助(插件侧简化版:bump 分配)
|
||||||
|
var arenaOff uint32
|
||||||
|
var arenaUsed uint32
|
||||||
|
|
||||||
|
func arenaWrite(b []byte) (SharedRef, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return SharedRef{}, nil
|
||||||
|
}
|
||||||
|
off := arenaUsed
|
||||||
|
if off == 0 {
|
||||||
|
off = 1
|
||||||
|
}
|
||||||
|
end := off + uint32(len(b))
|
||||||
|
if int(end) > len(region)-int(arenaOff) {
|
||||||
|
return SharedRef{}, fmt.Errorf("arena 空间不足")
|
||||||
|
}
|
||||||
|
copy(region[arenaOff+off:arenaOff+end], b)
|
||||||
|
arenaUsed = end
|
||||||
|
return SharedRef{Offset: arenaOff + off, Length: uint32(len(b))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ---- 全局状态 ----
|
// ---- 全局状态 ----
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -112,6 +152,7 @@ var (
|
|||||||
outputCleaners = map[string]func(string) string{}
|
outputCleaners = map[string]func(string) string{}
|
||||||
|
|
||||||
shm []byte
|
shm []byte
|
||||||
|
region []byte // 统一区域完整 mmap(用于 SharedRef 读写)
|
||||||
|
|
||||||
// 事件环(§3.6):fd 4 = 事件环段 mmap,fd 5 = eventfd 读端
|
// 事件环(§3.6):fd 4 = 事件环段 mmap,fd 5 = eventfd 读端
|
||||||
evtRingData []byte
|
evtRingData []byte
|
||||||
@ -1002,9 +1043,9 @@ func handleKernelRequest(req *rpcRequest) {
|
|||||||
|
|
||||||
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 SharedRef `json:"text_ref"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(req.Params, &p); err != nil {
|
if err := json.Unmarshal(req.Params, &p); err != nil {
|
||||||
respondErr(req.ID, fmt.Errorf("解析 Cleaner 参数: %w", err))
|
respondErr(req.ID, fmt.Errorf("解析 Cleaner 参数: %w", err))
|
||||||
@ -1025,7 +1066,14 @@ func handleKernelRequest(req *rpcRequest) {
|
|||||||
respondErr(req.ID, fmt.Errorf("%s %s 未注册 Cleaner", p.Scope, p.Name))
|
respondErr(req.ID, fmt.Errorf("%s %s 未注册 Cleaner", p.Scope, p.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respond(req.ID, map[string]interface{}{"text": cleaner(p.Text)})
|
input := string(p.TextRef.Slice(region))
|
||||||
|
output := cleaner(input)
|
||||||
|
outRef, err := arenaWrite([]byte(output))
|
||||||
|
if err != nil {
|
||||||
|
respondErr(req.ID, fmt.Errorf("arena 写入失败: %w", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respond(req.ID, map[string]interface{}{"text_ref": outRef})
|
||||||
|
|
||||||
case "stage.invoke":
|
case "stage.invoke":
|
||||||
handleStageInvoke(req)
|
handleStageInvoke(req)
|
||||||
@ -1150,6 +1198,10 @@ func handleHandshake(req *rpcRequest) {
|
|||||||
evtSize := binary.LittleEndian.Uint32(m[sbOffEvtSize:])
|
evtSize := binary.LittleEndian.Uint32(m[sbOffEvtSize:])
|
||||||
// shm 指向 StageContext 段,后续代码用 shm[off...] 访问该段内部字段
|
// shm 指向 StageContext 段,后续代码用 shm[off...] 访问该段内部字段
|
||||||
shm = m[ctxOff : ctxOff+ctxSize]
|
shm = m[ctxOff : ctxOff+ctxSize]
|
||||||
|
// region 保存完整 mmap 区域,供 SharedRef 读写 arena
|
||||||
|
region = m
|
||||||
|
arenaOff = binary.LittleEndian.Uint32(m[sbOffArenaOff:])
|
||||||
|
arenaUsed = 1
|
||||||
// 挂载事件环段 + 打开通知句柄(§13.1:EvtRing 在统一区域内)
|
// 挂载事件环段 + 打开通知句柄(§13.1:EvtRing 在统一区域内)
|
||||||
if p.EvtRingSize > 0 && evtSize > 0 {
|
if p.EvtRingSize > 0 && evtSize > 0 {
|
||||||
er := m[evtOff : evtOff+evtSize]
|
er := m[evtOff : evtOff+evtSize]
|
||||||
|
|||||||
Reference in New Issue
Block a user