From 9d930db4eaa0e852c99fa74fa5de27889f33ec3c Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Thu, 10 Sep 2026 21:28:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(plugindev):=20output.invoke=20=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E4=BB=8E=E5=85=B1=E4=BA=AB=E5=B8=A7=E8=AF=BB=E5=8F=82?= =?UTF-8?q?=E6=95=B0(=C2=A713.6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 内核侧 OutputInvokeParams 新增 Frame/ArgsLen,payload 不再内联在 RPC 报文里。 模板必须跟着读帧,否则 frameInput 拿不到参数、输出通道收到的 payload 为空—— 生产插件(如 qq)走的正是模板,模板不改这个改动就等于没做。 无帧时回退内联 args,保持对直连 RPC 调用方的兼容。 --- tools/plugindev/templates/proc_main.go.tmpl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/plugindev/templates/proc_main.go.tmpl b/tools/plugindev/templates/proc_main.go.tmpl index 94150e1..07692b5 100644 --- a/tools/plugindev/templates/proc_main.go.tmpl +++ b/tools/plugindev/templates/proc_main.go.tmpl @@ -1242,8 +1242,23 @@ func handleKernelRequest(req *rpcRequest) { var p struct { Channel string `json:"channel"` Args map[string]interface{} `json:"args"` + Frame SharedRef `json:"frame"` + ArgsLen uint32 `json:"args_len"` } json.Unmarshal(req.Params, &p) + // 参数:内核标定帧的前段(§13.6)。只有直连 RPC 的调用方(无帧) + // 才走内联 Args——生产路径永远走帧,大 payload 不再爆管道。 + args := p.Args + if !p.Frame.IsZero() { + if blob := frameInput(p.Frame, p.ArgsLen); len(blob) > 0 { + var decoded map[string]interface{} + if err := json.Unmarshal(blob, &decoded); err != nil { + respondErr(req.ID, fmt.Errorf("解析共享输出参数: %w", err)) + return + } + args = decoded + } + } handlerMu.RLock() h, ok := outputHandlers[p.Channel] handlerMu.RUnlock() @@ -1252,7 +1267,7 @@ func handleKernelRequest(req *rpcRequest) { return } // 同步返回真实结果——内核据此告知模型成功/失败,不再假成功(§9.4) - res, err := h(p.Args) + res, err := h(args) if err != nil { respondErr(req.ID, err) return