feat(agent): 云端 Agent - 增加上下文预算、任务事实与终态恢复保障
This commit is contained in:
1 parent
3bf21d79af
commit
b52bc9d5f2
61 files changed
+3512
-309
No files matched your search
@@ -43,6 +43,7 @@ func TestCloudAgentRefreshStepSnapshotHash(t *testing.T) {
|
||||
if err := db.First(&canvas, "id = ?", "agent-canvas").Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beforeRaw := canvas.PayloadJSON
|
||||
doc, err := creationDocument(canvas.PayloadJSON)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -56,6 +57,9 @@ func TestCloudAgentRefreshStepSnapshotHash(t *testing.T) {
|
||||
if latest == base {
|
||||
t.Fatal("测试前提不成立:画布哈希没变")
|
||||
}
|
||||
if err := s.repo.CreateCloudAgentCanvasMutation(&model.CloudAgentCanvasMutation{ID: "mutation-1", RunID: run.ID, UserID: run.UserID, CanvasID: run.CanvasID, StepID: state.Calls[0].ID, Operation: "canvas_apply_ops", BeforeSnapshotHash: base, AfterSnapshotHash: latest, BeforeJSON: beforeRaw, Status: "applied"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got = s.cloudAgentRefreshStepSnapshotHash(run, &state, state.Calls[1])
|
||||
var args struct {
|
||||
@@ -112,6 +116,9 @@ func TestCloudAgentRefreshStepSnapshotHash(t *testing.T) {
|
||||
if afterBind == latest {
|
||||
t.Fatal("测试前提不成立:提交第一条后画布哈希没变")
|
||||
}
|
||||
if err := s.repo.CreateCloudAgentCanvasMutation(&model.CloudAgentCanvasMutation{ID: "mutation-2", RunID: run.ID, UserID: run.UserID, CanvasID: run.CanvasID, StepID: state.Calls[1].ID, Operation: "generate_media_submit", BeforeSnapshotHash: latest, AfterSnapshotHash: afterBind, BeforeJSON: string(raw), Status: "applied"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fresh := s.cloudAgentRefreshStepSnapshotHash(run, &state, state.Calls[1])
|
||||
var freshArgs struct {
|
||||
SnapshotHash string `json:"snapshotHash"`
|
||||
@@ -149,3 +156,60 @@ func TestCloudAgentRefreshStepSnapshotHash(t *testing.T) {
|
||||
t.Fatalf("漏传 snapshotHash 应补当前媒体快照:got %s", truncateRunes(filledArgs.SnapshotHash, 12))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloudAgentRefreshStepSnapshotHashRejectsExternalWrites(t *testing.T) {
|
||||
s, db, a := agentMediaFixture(t)
|
||||
if sqlDB, err := db.DB(); err == nil {
|
||||
t.Cleanup(func() { _ = sqlDB.Close() })
|
||||
}
|
||||
baseCanvas, err := s.repo.CanvasProjectForUser("user", "agent-canvas")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
baseDoc, err := creationDocument(baseCanvas.PayloadJSON)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
base := cloudAgentCanvasHash(baseDoc)
|
||||
state := cloudAgentRuntime{Request: agentTestRequest(), Step: 1, CallIndex: 1, StepSnapshotHash: base}
|
||||
state.Request.CanvasID = "agent-canvas"
|
||||
state.Calls = []cloudAgentCall{agentMediaCall(a), agentMediaCall(a)}
|
||||
run := &model.CloudAgentExecution{ID: "run-current", UserID: "user", CanvasID: "agent-canvas"}
|
||||
|
||||
// A direct autosave or another tab has no current-run mutation record.
|
||||
directDoc := cloneCreationDocument(baseDoc)
|
||||
directDoc["nodes"] = append(creationMaps(directDoc["nodes"]), map[string]any{"id": "external-node", "type": "image"})
|
||||
directRaw, _ := json.Marshal(directDoc)
|
||||
if err := db.Model(&model.CanvasProject{}).Where("id = ?", "agent-canvas").Update("payload_json", string(directRaw)).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := s.cloudAgentRefreshStepSnapshotHash(run, &state, state.Calls[1])
|
||||
if got.Function.Arguments != state.Calls[1].Function.Arguments {
|
||||
t.Fatal("无记录的外部写入不能被吸收")
|
||||
}
|
||||
|
||||
// A different Agent run's mutation is also a conflict for this run.
|
||||
if err := db.Model(&model.CanvasProject{}).Where("id = ?", "agent-canvas").Update("payload_json", baseCanvas.PayloadJSON).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
otherDoc := cloneCreationDocument(baseDoc)
|
||||
otherDoc["nodes"] = append(creationMaps(otherDoc["nodes"]), map[string]any{"id": "other-run-node", "type": "image"})
|
||||
otherRaw, _ := json.Marshal(otherDoc)
|
||||
if err := db.Model(&model.CanvasProject{}).Where("id = ?", "agent-canvas").Update("payload_json", string(otherRaw)).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
otherHash := cloudAgentCanvasHash(otherDoc)
|
||||
if err := s.repo.CreateCloudAgentCanvasMutation(&model.CloudAgentCanvasMutation{ID: "mutation-other", RunID: "run-other", UserID: "user", CanvasID: "agent-canvas", StepID: "other-call", Operation: "canvas_apply_ops", BeforeSnapshotHash: base, AfterSnapshotHash: otherHash, Status: "applied"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got = s.cloudAgentRefreshStepSnapshotHash(run, &state, state.Calls[1])
|
||||
if got.Function.Arguments != state.Calls[1].Function.Arguments {
|
||||
t.Fatal("其他 Agent run 的写入不能被当前 run 吸收")
|
||||
}
|
||||
}
|
||||
|
||||
func cloneCreationDocument(doc map[string]any) map[string]any {
|
||||
raw, _ := json.Marshal(doc)
|
||||
copy, _ := creationDocument(string(raw))
|
||||
return copy
|
||||
}
|
||||
Reference in new issue
Block a user