Version: 0.9.55.dev.260429

后端:
1. analyze_health 候选复诊改为轻量 after brief 口径,候选模拟执行后只展示基础诊断结论,不再递归触发全局候选枚举,避免 score-only 评估阶段重复扫描和误判继续优化。

前端:
2. thinking_summary 支持同一条回复内多轮思考块——按 backendKey 维护独立阶段状态,final 后再次收到摘要会新建 reasoning block,避免多轮思考被合并、去重状态互相吞掉。
3. timeline 历史恢复改为复用后端事件 seq,正文、工具、状态、思考块都按原始顺序回放,减少刷新后消息块错位、插队和布局跳变。
4. 思考流式态下沉到当前活跃 reasoning block,只让正在输出的思考块闪光、显示游标和接收逐字追加,旧思考块完成后稳定折叠,不再被新一轮思考“复活”。
5. 清理助手消息重置逻辑,补齐 reasoning block、短摘要、耗时、折叠态和流式队列的状态回收,降低连续会话/重发时的残留干扰。
This commit is contained in:
Losita
2026-04-29 15:23:22 +08:00
parent bdf38f2f8d
commit d5b52b35ac
2 changed files with 223 additions and 68 deletions

View File

@@ -206,6 +206,38 @@ func buildAnalyzeHealthFinalDecisionBrief(
return decision
}
// buildAnalyzeHealthCandidateAfterBrief 生成候选执行后的轻量复诊摘要。
//
// 职责边界:
// 1. 只负责为 candidate.after / candidate.summary 提供“执行后看起来如何”的展示结论;
// 2. 不负责再次枚举 move/swap 候选,也不决定顶层 analyze_health 是否继续优化;
// 3. 输入是已经模拟执行后的 state/snapshot输出沿用 analyzeHealthDecisionBase 的字段语义。
func buildAnalyzeHealthCandidateAfterBrief(
state *ScheduleState,
snapshot analyzeHealthSnapshot,
) analyzeHealthDecisionBase {
base := buildAnalyzeHealthDecisionBase(state, snapshot)
decision := analyzeHealthDecisionBase{
ShouldContinueOptimize: base.ShouldContinueOptimize,
PrimaryProblem: base.PrimaryProblem,
ProblemScope: base.ProblemScope,
IsForcedImperfection: base.IsForcedImperfection,
RecommendedOperation: base.RecommendedOperation,
}
if !shouldEnterHealthCandidateLoop(base) {
decision.ShouldContinueOptimize = false
return decision
}
// 1. candidate.after 位于候选模拟内层,不能再跑全局候选枚举。
// 2. 顶层 buildAnalyzeHealthDecisionV2 已经负责严谨筛选“是否值得继续优化”;
// 这里保留基础诊断即可,避免每个候选递归触发 score-only 全局扫描。
// 3. 若仍存在基础诊断认为可优化的问题,则如实展示给前端和 LLM下一轮会再次调用
// analyze_health 做正式复诊,作为真正的收口依据。
return decision
}
// pickPrimaryHealthProblem 选择当前最值得处理的局部问题。
func pickPrimaryHealthProblem(state *ScheduleState, snapshot analyzeHealthSnapshot) (analyzeHealthProblem, bool) {
best := analyzeHealthProblem{}
@@ -868,7 +900,7 @@ func evaluateHealthCandidateOutcome(
operation string,
moveCost int,
) (string, int, analyzeHealthDecisionBase, bool) {
afterDecision := buildAnalyzeHealthFinalDecisionBrief(afterState, after)
afterDecision := buildAnalyzeHealthCandidateAfterBrief(afterState, after)
effect, score, ok := evaluateHealthCandidateScoreOnly(
baseline,
after,