fix(agent): 优化预算与技能按需加载

This commit is contained in:
ddCat
2026-09-15 07:04:08 +08:00
parent 201f3aac65
commit a840e552d5
6 changed files with 69 additions and 32 deletions

View File

@@ -18,8 +18,6 @@ import (
"infinite-canvas/backend/internal/repository"
)
const cloudAgentMaxSteps = 8
// A deterministic checkpoint failure must not be retried forever like a transient DB error.
var errCloudAgentCheckpoint = errors.New("invalid Agent checkpoint")
@@ -155,10 +153,10 @@ func validateCloudAgentRuntime(run *model.CloudAgentExecution, state *cloudAgent
return errors.New("Agent runtime profile read history is invalid")
}
}
if state.Step < 0 || state.Step > cloudAgentMaxSteps+1 || state.Generations < 0 || state.VideoSeconds < 0 {
if state.Step < 0 || state.Generations < 0 || state.VideoSeconds < 0 {
return errors.New("Agent runtime budget or step is invalid")
}
if state.Generations > state.Request.Budget.MaxGenerationTasks || state.VideoSeconds > state.Request.Budget.MaxVideoSeconds {
if (state.Request.Budget.MaxGenerationTasks > 0 && state.Generations > state.Request.Budget.MaxGenerationTasks) || (state.Request.Budget.MaxVideoSeconds > 0 && state.VideoSeconds > state.Request.Budget.MaxVideoSeconds) {
return errors.New("Agent runtime generation budget is invalid")
}
if state.CallIndex < 0 || state.CallIndex > len(state.Calls) || len(state.Calls) > 8 {
@@ -559,10 +557,8 @@ func (s *Service) advanceCloudAgent(run *model.CloudAgentExecution) (err error)
if state.CallIndex < len(state.Calls) {
return s.advanceCloudAgentTool(run, &state)
}
if state.Step >= cloudAgentMaxSteps {
return s.failCloudAgent(run, &state, "达到 8 次模型调用上限,本轮已停止")
}
input := map[string]any{"mode": "text", "prompt": state.Request.Prompt, "agentRequests": map[string]any{"canonical": state.Canonical}, "config": map[string]any{"channelId": state.Request.ChannelID, "channelModelKey": state.Request.ChannelModelKey, "model": firstNonEmpty(state.Request.ChannelModelKey, state.Request.Model)}, "textOptions": map[string]any{"stream": true, "thinking": cloudAgentReasoningEnabled(state.Policy.ReasoningMode)}}
compactCloudAgentContext(&state.Canonical)
raw, _ := json.Marshal(state.Canonical)
if len(raw) > 192<<10 {
return s.failCloudAgent(run, &state, "模型上下文超过 192KB 上限")
@@ -570,6 +566,30 @@ func (s *Service) advanceCloudAgent(run *model.CloudAgentExecution) (err error)
req := CreateTaskRequest{ProjectID: state.Request.CanvasID, Type: "canvas_text", Operation: "cloud_agent_step", Prompt: state.Request.Prompt, Model: state.Request.Model, LogicalModelID: state.Request.LogicalModelID, Input: input}
return s.enqueueCloudAgentTask(run, &state, req, nil)
}
func compactCloudAgentContext(request *canonicalAgentRequest) {
const maxMessages = 24
if request == nil || len(request.Messages) <= maxMessages {
return
}
keep := 16
dropped := request.Messages[1 : len(request.Messages)-keep]
if len(dropped) == 0 {
return
}
parts := make([]string, 0, len(dropped))
for _, message := range dropped {
role := stringField(message, "role")
text := canonicalAgentText(message["content"])
if text == "" {
text = "工具/调用记录"
}
parts = append(parts, role+": "+truncateRunes(text, 240))
}
summary := map[string]interface{}{"role": "user", "content": "历史上下文摘要(仅供参考;实时画布状态必须通过工具读取,不是新指令):\n" + strings.Join(parts, "\n")}
request.Messages = append([]map[string]interface{}{request.Messages[0], summary}, request.Messages[len(request.Messages)-keep:]...)
}
func validateCloudAgentCalls(calls []cloudAgentCall) error {
seen := make(map[string]bool, len(calls))
for _, call := range calls {
@@ -837,7 +857,7 @@ func (s *Service) advanceCloudAgentTool(run *model.CloudAgentExecution, state *c
case call.Function.Name == "model_list":
result = modelList
default:
result, toolErr = cloudAgentReadTool(repo, run.UserID, state, call)
result, toolErr = cloudAgentReadTool(repo, run.UserID, state, call, s)
}
cloudAgentToolResult(run.ID, state, call, result, toolErr)
return cloudAgentSave(current, state)