fix(agent): Agent 运行 - 重复读取改为软收敛并保留可纠正的媒体失败原因

重复只读和同版本识图不再把运行标成失败,下一步暂时收起只读工具。媒体能力错误改为可纠正,准入失败保留安全原因。
This commit is contained in:
ddcat666 committed 2026-10-10 20:20:09 +08:00
1 parent 37b44444f0
commit 1bbc95b996
15 files changed
+394 -52

No files matched your search

@@ -380,10 +380,72 @@ func TestCloudAgentVisionBlocksSameResourceInSameCanvasRevision(t *testing.T) {
state.ImageInspectionReads = map[string]int{inspection.CacheKey: 1}
refreshCall := cloudAgentStoryboardCall(t, "canvas_inspect_image", "inspect-refresh", map[string]any{"nodeId": "cat", "refresh": true})
_, err = s.prepareCloudAgentImageInspection("user", "agent-canvas", &state, refreshCall)
var loopErr *cloudAgentReadLoopError
if !errors.As(err, &loopErr) {
t.Fatalf("refresh should not re-read the same resource in the same revision: %v", err)
second, err := s.prepareCloudAgentImageInspection("user", "agent-canvas", &state, refreshCall)
if err != nil {
t.Fatalf("repeated visual read should converge to a receipt, got: %v", err)
}
receipt := second.(cloudAgentImageInspection)
if receipt.ImageURL != "" || receipt.Receipt["repeat"] != true || receipt.CacheKey != inspection.CacheKey {
t.Fatalf("repeated visual read did not return a stable text receipt: %+v", receipt)
}
}
func TestCloudAgentVisionRepeatReadSoftNudgesRuntime(t *testing.T) {
s, _, _ := cloudAgentVisionFixture(t)
req := agentTestRequest()
req.VisionEnabled = true
root, err := s.CreateCloudAgentRun("user", req, "")
if err != nil {
t.Fatal(err)
}
run, err := s.repo.CloudAgent("user", root.ID)
if err != nil {
t.Fatal(err)
}
state, err := cloudAgentDecode(run)
if err != nil {
t.Fatal(err)
}
state.Request.VisionEnabled = true
firstCall := cloudAgentStoryboardCall(t, "canvas_inspect_image", "inspect-first", map[string]any{"nodeId": "cat"})
first, err := s.prepareCloudAgentImageInspection("user", "agent-canvas", &state, firstCall)
if err != nil {
t.Fatal(err)
}
cacheKey := first.(cloudAgentImageInspection).CacheKey
state.ImageInspectionReads = map[string]int{cacheKey: 1}
state.Calls = []cloudAgentCall{cloudAgentStoryboardCall(t, "canvas_inspect_image", "inspect-repeat", map[string]any{"nodeId": "cat", "refresh": true})}
state.CallIndex = 0
if err := s.repo.MutateCloudAgent("user", run.ID, run.Revision, func(current *model.CloudAgentExecution, _ *repository.Repository) error {
return cloudAgentSave(current, &state)
}); err != nil {
t.Fatal(err)
}
run, err = s.repo.CloudAgent("user", root.ID)
if err != nil {
t.Fatal(err)
}
state, err = cloudAgentDecode(run)
if err != nil {
t.Fatal(err)
}
if err := s.advanceCloudAgentTool(run, &state); err != nil {
t.Fatal(err)
}
output, err := s.CloudAgentRun("user", root.ID)
if err != nil {
t.Fatal(err)
}
if output.Status != "running" {
t.Fatalf("repeat visual read terminated the run: %+v", output)
}
hasGuard, hasFailure := false, false
for _, event := range output.Events {
hasGuard = hasGuard || event.Type == "read_loop_guard"
hasFailure = hasFailure || event.Type == "run_failed"
}
if !hasGuard || hasFailure {
t.Fatalf("repeat visual read did not preserve a soft guard: %+v", output.Events)
}
}
@@ -407,7 +469,7 @@ func TestCloudAgentVisionHasPerRunInspectionBudget(t *testing.T) {
}
}
func TestCloudAgentVisionBudgetStopsRunBeforeAnotherModelStep(t *testing.T) {
func TestCloudAgentVisionBudgetSoftNudgesBeforeAnotherModelStep(t *testing.T) {
s, _, _ := cloudAgentVisionFixture(t)
req := agentTestRequest()
req.VisionEnabled = true
@@ -447,8 +509,16 @@ func TestCloudAgentVisionBudgetStopsRunBeforeAnotherModelStep(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if output.Status != "failed" || !strings.Contains(output.FailureMessage, "识图调用已达到安全上限") {
t.Fatalf("inspection budget did not terminate the run: %+v", output)
if output.Status != "running" {
t.Fatalf("inspection budget terminated the run: %+v", output)
}
hasGuard, hasFailure := false, false
for _, event := range output.Events {
hasGuard = hasGuard || event.Type == "read_loop_guard"
hasFailure = hasFailure || event.Type == "run_failed"
}
if !hasGuard || hasFailure {
t.Fatalf("inspection budget did not soft-nudge the next model request: %+v", output.Events)
}
}