mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-10-31 06:17:25 +00:00
fix(proc,qq)!: shm 模板 v2 —— fExtraBag 透传插件自建 Extra 键;qq 身份可序列化绑帧
内核 shm 桥 v2 前(见主仓同步提交)只透传 4 个具名 Extra 键,插件自建键 (qq 的 qq_auth 绑帧身份)在 stage 之间静默丢失 → before_toolcall 永远回落 可变全局身份 → 权限门绑帧在 proc 插件下整体失效(owner 被误拒/非 owner 可能被误放,2026-10-12 生产实证)。 模板(proc_main.go.tmpl): - shmStageFieldCount 18→19、shmVersion 1→2(与内核镜像同步) - fExtraBag:具名 4 键之外的自建键整体 JSON 装袋,read/snapshot/dirty 全链接入 - ReadInto:bag 先打平、具名键后覆盖(具名键永远赢,防御袋污染) qq 插件: - qqAuthContext 字段导出 + json tag:非导出字段过 JSON 桥会静默丢空 (原根因链一环) - authOnFrame 双形态:值形态(进程内/单测)+ map 形态(proc 桥往返, 数字 float64);半截身份拒绝 —— 宁回落全局也不猜(owner 误判即提权) - authFromMap 按 json tag 重建,逐字段校验类型 判据(plugin_test.go):往返无损/降权保持/半截拒绝(逐键)/帧身份优先于 全局(含 owner 被误拒的原始故障场景反向)。变异 Q1-Q4 全杀。
This commit is contained in:
@ -56,7 +56,7 @@ const (
|
||||
// ---- StageContext 段内部布局(与内核 internal/plugin/proc/shm.go 一致)----
|
||||
|
||||
const (
|
||||
shmStageFieldCount = 18
|
||||
shmStageFieldCount = 19
|
||||
shmSliceSize = 8
|
||||
|
||||
shmOffMagic = 0
|
||||
@ -68,7 +68,7 @@ const (
|
||||
shmOffSeq = 24
|
||||
|
||||
shmMagic = 0x48415348
|
||||
shmVersion = 1
|
||||
shmVersion = 2
|
||||
)
|
||||
|
||||
// 字段索引(顺序须与内核 stageField 枚举一致)
|
||||
@ -91,8 +91,35 @@ const (
|
||||
fExtraMediaType
|
||||
fExtraInputSource
|
||||
fExtraOutputChannel
|
||||
// fExtraBag:Extra 里具名 4 键之外的全部插件自建键(整体 JSON)。
|
||||
// 插件可写:绑定帧态(如 qq_auth)就存这里;跨 stage 经内核回读存活。
|
||||
fExtraBag
|
||||
)
|
||||
|
||||
// shmNamedExtraKeys 是被提升为具名字段的 Extra 键;bag 打平时必须排除,
|
||||
// 否则同一键会被具名字段与 bag 各带一份。
|
||||
var shmNamedExtraKeys = map[string]bool{
|
||||
"media_blocks": true, "media_type": true, "input_source": true, "output_channel": true,
|
||||
}
|
||||
|
||||
// shmBagFromExtra 收集 Extra 里非具名键;无额外键返回 nil。
|
||||
func shmBagFromExtra(extra map[string]interface{}) map[string]interface{} {
|
||||
if len(extra) == 0 {
|
||||
return nil
|
||||
}
|
||||
var bag map[string]interface{}
|
||||
for k, v := range extra {
|
||||
if shmNamedExtraKeys[k] {
|
||||
continue
|
||||
}
|
||||
if bag == nil {
|
||||
bag = make(map[string]interface{})
|
||||
}
|
||||
bag[k] = v
|
||||
}
|
||||
return bag
|
||||
}
|
||||
|
||||
const (
|
||||
flagNoMemory = 0
|
||||
flagResponseSet = 1
|
||||
@ -518,6 +545,15 @@ func readStageContext() (*sdk.StageContext, error) {
|
||||
}
|
||||
|
||||
extra := map[string]interface{}{}
|
||||
// bag 先打平,具名键随后覆盖 → 具名键永远赢(与内核 ReadInto 同构;
|
||||
// 防御 bag 里混入具名键时用陈旧值顶掉具名字段)。
|
||||
var bag map[string]interface{}
|
||||
if err := unmarshalField(fExtraBag, &bag); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range bag {
|
||||
extra[k] = v
|
||||
}
|
||||
for _, pair := range []struct {
|
||||
field int
|
||||
key string
|
||||
@ -580,6 +616,8 @@ func takeStageSnapshot(sc *sdk.StageContext) *stageSnapshot {
|
||||
sn.jsons[fMemory] = marshal(sc.Memory, len(sc.Memory))
|
||||
sn.jsons[fTokenUsage] = marshal(sc.TokenUsage, len(sc.TokenUsage))
|
||||
sn.jsons[fErrors] = marshal(sc.Errors, len(sc.Errors))
|
||||
bag := shmBagFromExtra(sc.Extra)
|
||||
sn.jsons[fExtraBag] = marshal(bag, len(bag))
|
||||
|
||||
if sc.Response != nil {
|
||||
sn.response = *sc.Response
|
||||
|
||||
Reference in New Issue
Block a user