package flow import ( "sort" "ai-agent/workflow/model/entity" ) // segmentGenerateMaxAttempts 视频段生成最大尝试次数(失败自动重试 1 次,共 2 次尝试),参数化可调 const segmentGenerateMaxAttempts = 2 // planSegmentResume 段级续跑决策:段身份取列表位置(0-based,paramsList 顺序即段序), // 把各段映射到"是否需重新生成"。savedMap 为该节点已成功段(段序号 → {key,url}); // 段在表中缺失或地址为空则需重新生成。返回值与 paramsList 对齐。 // 全新执行(savedMap 为 nil/空)时全部需生成。 // 不用 params["segment_index"] 作为段身份:真实链路(上游 split_shots_pipeline 转写 → // 下游 split_segment 按 __segment_fields 拆分,invokePreTool 剥离 __ 内部键)下 // paramsList 只有模型参数;列表位置互不重复、顺序即段序、参数一致时跨 reExecute 稳定。 func planSegmentResume(paramsList []map[string]any, savedMap map[int]entity.SegmentRef) (idxList []int, needGen []bool) { idxList = make([]int, len(paramsList)) needGen = make([]bool, len(paramsList)) for i := range paramsList { idxList[i] = i ref, ok := savedMap[i] needGen[i] = !ok || ref.URL == "" } return } // mergeSegmentOutputs 把复用段与新生段按段序号升序合并为 concat 输入列表(列表顺序即拼接顺序)。 // 复用段重建 {key:url} 记录(key 保持模型原输出字段,避免下游引用失配);新生段沿用模型原输出。 // 任一段既无复用又无生成结果(生成空)则跳过——与现有"空段贡献空"行为一致,最终由 concat 校验兜底。 func mergeSegmentOutputs(idxList []int, needGen []bool, newRes [][]map[string]any, savedMap map[int]entity.SegmentRef) []map[string]any { type segOutput struct { idx int recs []map[string]any } out := make([]segOutput, 0, len(idxList)) for i, idx := range idxList { if needGen[i] { if len(newRes[i]) > 0 { out = append(out, segOutput{idx: idx, recs: newRes[i]}) } continue } if ref, ok := savedMap[idx]; ok && ref.URL != "" { out = append(out, segOutput{idx: idx, recs: []map[string]any{{ref.Key: ref.URL}}}) } } sort.SliceStable(out, func(a, b int) bool { return out[a].idx < out[b].idx }) var merged []map[string]any for _, o := range out { merged = append(merged, o.recs...) } return merged }