From 4dd3b554a5bab005cc128420ad7ea96c8d9e504c Mon Sep 17 00:00:00 2001 From: AetherNo2332 <130164460+AetherNo2332@users.noreply.github.com> Date: Mon, 21 Sep 2026 07:30:57 +0800 Subject: [PATCH] =?UTF-8?q?fix(agent):=20=E7=94=BB=E5=B8=83=E5=86=99?= =?UTF-8?q?=E5=85=A5=20-=20=E6=BC=8F=20patch=20=E6=8C=89=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=9B=9E=E7=BB=99=E6=A8=A1=E5=9E=8B=E8=80=8C?= =?UTF-8?q?=E4=B8=8D=E6=98=AF=E7=BB=88=E6=AD=A2=E6=95=B4=E8=BD=AE=20(#566)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original-Commit: a7df2b57c72e479200b82d0af88446d43fa9f9dd fix(agent): 画布写入 - 漏 patch 按参数错误回给模型而不是终止整轮 审批模式下模型用 canvas_apply_ops 做 update_node 时漏了 patch,准入预检直接返回普通 BadAuthRequest,运行期按"准入失败"处理 → 整轮 failed,用户只看得到一句"更新节点必须提供 patch", 模型没有改正机会。批量创作表、分镜、画布读取参数都已把同类错误包成 cloudAgentArgumentError (运行期 errors.As 后作为工具结果回给模型重试),这里补齐。 未知画布写操作仍按准入失败终止(既有用例断言不变);新增用例同时钉住这两条。 --- .../app/cloud_agent_approval_preview.go | 5 +++- .../app/cloud_agent_approval_preview_test.go | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/backend/internal/app/cloud_agent_approval_preview.go b/backend/internal/app/cloud_agent_approval_preview.go index bfa1e69d8..57bcd3163 100644 --- a/backend/internal/app/cloud_agent_approval_preview.go +++ b/backend/internal/app/cloud_agent_approval_preview.go @@ -153,7 +153,10 @@ func applyCloudAgentCanvasPlan(doc map[string]any, ops []agentCanvasOp) ([]cloud }) case "update_node": if len(op.Patch) == 0 { - return nil, BadAuthRequest("更新节点必须提供 patch") + // 漏字段是模型照 schema 就能自己修好的参数错误:当成工具结果回给它重试, + // 而不是判整轮失败(用户只在失败提示里看到一句"必须提供 patch")。 + // 未知操作类型仍按准入失败终止(cloud_agent_test.go 有用例断言这一行为)。 + return nil, &cloudAgentArgumentError{BadAuthRequest("更新节点必须提供 patch")} } if index < 0 { return nil, BadAuthRequest("只能更新现有且受 Agent 支持的节点") diff --git a/backend/internal/app/cloud_agent_approval_preview_test.go b/backend/internal/app/cloud_agent_approval_preview_test.go index 844b17ae9..033f9582c 100644 --- a/backend/internal/app/cloud_agent_approval_preview_test.go +++ b/backend/internal/app/cloud_agent_approval_preview_test.go @@ -2,6 +2,7 @@ package app import ( "encoding/json" + "errors" "strings" "testing" ) @@ -81,3 +82,25 @@ func TestCloudAgentCanvasApprovalPreviewRejectsUnknownTargetInsteadOfFallingBack t.Fatalf("unknown target was not rejected: %v", err) } } + +// 漏 patch 必须是**可恢复的参数错误**:运行期会把它当工具结果回给模型重试, +// 而不是把整轮判死;未知操作类型(例如删除)仍按准入失败终止。 +func TestCloudAgentCanvasApprovalPreviewTreatsMissingPatchAsArgumentError(t *testing.T) { + doc, err := creationDocument(`{"nodes":[{"id":"image-1","type":"image","title":"参考图"}],"connections":[]}`) + if err != nil { + t.Fatal(err) + } + _, err = applyCloudAgentCanvasPlan(doc, []agentCanvasOp{{Type: "update_node", ID: "image-1"}}) + var argumentErr *cloudAgentArgumentError + if !errors.As(err, &argumentErr) { + t.Fatalf("漏 patch 应当是可恢复的参数错误,实际:%v", err) + } + + _, err = applyCloudAgentCanvasPlan(doc, []agentCanvasOp{{Type: "delete_node", ID: "image-1"}}) + if err == nil { + t.Fatal("未知画布写操作必须仍然报错") + } + if errors.As(err, &argumentErr) { + t.Fatalf("未知画布写操作不能被当成可恢复的参数错误:%v", err) + } +}