feat(agent): Agent 工作台 - 计划插话记忆、统一模型选择器并修复摘要与视频入库

将计划清单、运行中插话和个人记忆接入云端 Agent;全站模型选择器统一为左右二级菜单。画布摘要按预算截断不再整轮拒绝,首页视频未知宽高可入库。README 补充贡献者 morrow。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ddCat
2026-09-17 20:21:25 +08:00
parent b6bae4f957
commit 6892732b06
80 changed files with 7364 additions and 182 deletions

View File

@@ -0,0 +1,77 @@
package app
import (
"strings"
"testing"
"infinite-canvas/backend/internal/model"
)
func TestCloudAgentContinuationReplySplitsFactsFromAssistantText(t *testing.T) {
task := &model.Task{Status: model.TaskStatusSucceeded, ResultJSON: `{"text":"已完成"}`}
run := &CloudAgentRun{
ID: "ag1",
Status: "failed",
Events: []CloudAgentEvent{
{Type: "assistant_message", Payload: map[string]any{"text": "先看画布"}},
{Type: "tool_completed", Payload: map[string]any{"toolName": "canvas_get_state", "nodeId": "n1"}},
{Type: "run_failed", Payload: map[string]any{"reason": "cancelled"}},
},
}
reply, context, err := cloudAgentContinuationReply(task, run)
if err != nil {
t.Fatal(err)
}
if reply != "先看画布" {
t.Fatalf("reply 应是上一轮 assistant 正文,got %q", reply)
}
if context == "" {
t.Fatal("失败轮次必须留下收束摘要")
}
if strings.Contains(reply, "上一轮已结束") || strings.Contains(reply, "canvas_get_state") {
t.Fatal("摘要不能拼进 assistant 历史")
}
if strings.Contains(context, "canvas_get_state") || strings.Contains(context, `"event"`) {
t.Fatalf("摘要不得把工具流水当成本轮目标:%s", context)
}
if !strings.Contains(context, "上一轮已结束(failed)") || !strings.Contains(context, "当前用户消息") {
t.Fatalf("失败摘要不对:%s", context)
}
}
func TestCloudAgentContinuationOmitsQuietCompletedTurns(t *testing.T) {
task := &model.Task{Status: model.TaskStatusSucceeded, ResultJSON: `{"text":"好"}`}
run := &CloudAgentRun{
Status: "completed",
Events: []CloudAgentEvent{
{Type: "assistant_message", Payload: map[string]any{"text": "好"}},
{Type: "tool_completed", Payload: map[string]any{"toolName": "canvas_get_state"}},
},
}
reply, context, err := cloudAgentContinuationReply(task, run)
if err != nil {
t.Fatal(err)
}
if reply != "好" || context != "" {
t.Fatalf("安静完成的一轮不应再塞执行流水:reply=%q context=%q", reply, context)
}
}
func TestCloudAgentContinuationKeepsSubmittedTaskIDs(t *testing.T) {
task := &model.Task{Status: model.TaskStatusSucceeded}
run := &CloudAgentRun{
Status: "completed",
Events: []CloudAgentEvent{
{Type: "assistant_message", Payload: map[string]any{"text": "已提交"}},
{Type: "generation_task_created", Payload: map[string]any{"taskId": "task-1"}},
{Type: "tool_completed", Payload: map[string]any{"result": map[string]any{"taskId": "task-2", "taskSubmitted": true}}},
},
}
_, context, err := cloudAgentContinuationReply(task, run)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(context, "task-1") || !strings.Contains(context, "task-2") || !strings.Contains(context, "不要重发") {
t.Fatalf("已提交任务应留下防重发提示:%s", context)
}
}