package multiagent import ( "fmt" "strings" "unicode/utf8" "cyberstrike-ai/internal/config" "github.com/cloudwego/eino/adk/prebuilt/planexecute" ) // plan_execute 的 Replanner / Executor prompt 会线性拼接每步 Result;无界时易撑爆上下文。 // 此处仅约束「写入模型 prompt 的视图」,不修改 Eino session 中的原始 ExecutedSteps。 const ( defaultPlanExecuteMaxStepResultRunes = 4000 defaultPlanExecuteKeepLastSteps = 8 // Backward-compatible aliases for tests and existing references. planExecuteMaxStepResultRunes = defaultPlanExecuteMaxStepResultRunes planExecuteKeepLastSteps = defaultPlanExecuteKeepLastSteps ) func truncateRunesWithSuffix(s string, maxRunes int, suffix string) string { if maxRunes <= 0 || s == "" { return s } rs := []rune(s) if len(rs) <= maxRunes { return s } return string(rs[:maxRunes]) + suffix } // capPlanExecuteExecutedSteps 折叠较早步骤、截断单步过长结果,供 prompt 使用。 func capPlanExecuteExecutedSteps(steps []planexecute.ExecutedStep) []planexecute.ExecutedStep { return capPlanExecuteExecutedStepsWithConfig(steps, nil) } func capPlanExecuteExecutedStepsWithConfig(steps []planexecute.ExecutedStep, mwCfg *config.MultiAgentEinoMiddlewareConfig) []planexecute.ExecutedStep { if len(steps) == 0 { return steps } maxStepResultRunes := defaultPlanExecuteMaxStepResultRunes keepLastSteps := defaultPlanExecuteKeepLastSteps if mwCfg != nil { maxStepResultRunes = mwCfg.PlanExecuteMaxStepResultRunesEffective() keepLastSteps = mwCfg.PlanExecuteKeepLastStepsEffective() } out := make([]planexecute.ExecutedStep, 0, len(steps)+1) start := 0 if len(steps) > keepLastSteps { start = len(steps) - keepLastSteps var b strings.Builder b.WriteString(fmt.Sprintf("(上文已完成 %d 步;此处仅保留步骤标题以节省上下文,完整输出已省略。后续 %d 步仍保留正文。)\n", start, keepLastSteps)) for i := 0; i < start; i++ { b.WriteString(fmt.Sprintf("- %s\n", steps[i].Step)) } out = append(out, planexecute.ExecutedStep{ Step: "[Earlier steps — titles only]", Result: strings.TrimRight(b.String(), "\n"), }) } suffix := "\n…[step result truncated]" for i := start; i < len(steps); i++ { e := steps[i] if utf8.RuneCountInString(e.Result) > maxStepResultRunes { e.Result = truncateRunesWithSuffix(e.Result, maxStepResultRunes, suffix) } out = append(out, e) } return out }